Commit 594b2d9a authored by timothy@apple.com's avatar timothy@apple.com
Browse files

Implement basic versions of the TimelineOverview graphs.

https://bugs.webkit.org/show_bug.cgi?id=127184

Reviewed by Joseph Pecoraro.

* UserInterface/LayoutTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.layout > .timeline-record-bar):
(.timeline-overview-graph.layout > .timeline-record-bar > .segment):

* UserInterface/LayoutTimelineOverviewGraph.js: Added.
(WebInspector.LayoutTimelineOverviewGraph.prototype.reset):
(WebInspector.LayoutTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.LayoutTimelineOverviewGraph.prototype._layoutTimelineRecordAdded):

* UserInterface/Main.html: Added new files.

* UserInterface/NetworkTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.network):
(.timeline-overview-graph.network > .graph-row):
(.timeline-overview-graph.network > .graph-row > .bar):
(.timeline-overview-graph.network > .graph-row > .bar.inactive):
(.timeline-overview-graph.network > .graph-row > .bar.unfinished):
(.timeline-overview-graph.network > .graph-row > .bar:not(.inactive)):
(.timeline-overview-graph.network:nth-child(even) > .graph-row > .bar:not(.inactive)):

* UserInterface/NetworkTimelineOverviewGraph.js: Added.
(WebInspector.NetworkTimelineOverviewGraph.prototype.reset):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout.updateElementPosition):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout.createBar):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded.compareByStartTime):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded.insertObjectIntoSortedArray):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded):

* UserInterface/ScriptTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.script > .timeline-record-bar):
(.timeline-overview-graph.script > .timeline-record-bar > .segment):

* UserInterface/ScriptTimelineOverviewGraph.js: Added.
(WebInspector.ScriptTimelineOverviewGraph.prototype.reset):
(WebInspector.ScriptTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.ScriptTimelineOverviewGraph.prototype._scriptTimelineRecordAdded):

* UserInterface/TimelineContentView.js:
(WebInspector.TimelineContentView.prototype._showTimelineView):
(WebInspector.TimelineContentView.prototype._update):
(WebInspector.TimelineContentView.prototype._recordingReset):
Create and keep the graphs informed.

* UserInterface/TimelineDataGridNode.js:
(WebInspector.TimelineDataGridNode):
(WebInspector.TimelineDataGridNode.prototype.refreshGraph):
Combine records that might overlap.

* UserInterface/TimelineOverview.css:
(.timeline-overview > .graphs-container):
(.timeline-overview > .graphs-container > .timeline-overview-graph):
(.timeline-overview > .graphs-container > .timeline-overview-graph:nth-child(even)):
(.timeline-overview > .graphs-container > .timeline-overview-graph:not(:first-child)):
Add the graph rows with alternating stripe.

* UserInterface/TimelineOverview.js:
(WebInspector.TimelineOverview):
(WebInspector.TimelineOverview.prototype.set startTime):
(WebInspector.TimelineOverview.prototype.get currentTime):
(WebInspector.TimelineOverview.prototype.set currentTime):
(WebInspector.TimelineOverview.prototype.updateLayout):
(WebInspector.TimelineOverview.prototype.updateLayoutIfNeeded):
Track currentTime in a member variable and let TimelineOverview manage the current time marker.

* UserInterface/TimelineOverviewGraph.js: Added.
(WebInspector.TimelineOverviewGraph):
(WebInspector.TimelineOverviewGraph.prototype.get zeroTime):
(WebInspector.TimelineOverviewGraph.prototype.set zeroTime):
(WebInspector.TimelineOverviewGraph.prototype.get startTime):
(WebInspector.TimelineOverviewGraph.prototype.set startTime):
(WebInspector.TimelineOverviewGraph.prototype.get endTime):
(WebInspector.TimelineOverviewGraph.prototype.set endTime):
(WebInspector.TimelineOverviewGraph.prototype.get currentTime):
(WebInspector.TimelineOverviewGraph.prototype.set currentTime):
(WebInspector.TimelineOverviewGraph.prototype.reset):
(WebInspector.TimelineOverviewGraph.prototype.updateLayout):
(WebInspector.TimelineOverviewGraph.prototype.updateLayoutIfNeeded):
(WebInspector.TimelineOverviewGraph.prototype.needsLayout):

* UserInterface/TimelineRecordBar.css:
(.timeline-record-bar > .segment):
(.timeline-record-bar.unfinished > .segment):
(.timeline-record-bar > .segment.inactive + .segment):
(.timeline-record-bar.timeline-record-type-network > .segment.inactive):

* UserInterface/TimelineRecordBar.js:
(WebInspector.TimelineRecordBar):
(WebInspector.TimelineRecordBar.recordsCannotBeCombined):
(WebInspector.TimelineRecordBar.prototype.get records):
(WebInspector.TimelineRecordBar.prototype.set records):
(WebInspector.TimelineRecordBar.prototype.refresh):
Make TimelineRecordBar support multiple records.

* UserInterface/TimelineRuler.css:
(.timeline-ruler > .markers):
(.timeline-ruler > .selection-handle):
(.timeline-ruler > .shaded-area):
Add some z-index values to stay above graph elements.

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162419 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 387f50ed
2014-01-19 Timothy Hatcher <timothy@apple.com>
Implement basic versions of the TimelineOverview graphs.
https://bugs.webkit.org/show_bug.cgi?id=127184
Reviewed by Joseph Pecoraro.
* UserInterface/LayoutTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.layout > .timeline-record-bar):
(.timeline-overview-graph.layout > .timeline-record-bar > .segment):
* UserInterface/LayoutTimelineOverviewGraph.js: Added.
(WebInspector.LayoutTimelineOverviewGraph.prototype.reset):
(WebInspector.LayoutTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.LayoutTimelineOverviewGraph.prototype._layoutTimelineRecordAdded):
* UserInterface/Main.html: Added new files.
* UserInterface/NetworkTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.network):
(.timeline-overview-graph.network > .graph-row):
(.timeline-overview-graph.network > .graph-row > .bar):
(.timeline-overview-graph.network > .graph-row > .bar.inactive):
(.timeline-overview-graph.network > .graph-row > .bar.unfinished):
(.timeline-overview-graph.network > .graph-row > .bar:not(.inactive)):
(.timeline-overview-graph.network:nth-child(even) > .graph-row > .bar:not(.inactive)):
* UserInterface/NetworkTimelineOverviewGraph.js: Added.
(WebInspector.NetworkTimelineOverviewGraph.prototype.reset):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout.updateElementPosition):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout.createBar):
(WebInspector.NetworkTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded.compareByStartTime):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded.insertObjectIntoSortedArray):
(WebInspector.NetworkTimelineOverviewGraph.prototype._networkTimelineRecordAdded):
* UserInterface/ScriptTimelineOverviewGraph.css: Added.
(.timeline-overview-graph.script > .timeline-record-bar):
(.timeline-overview-graph.script > .timeline-record-bar > .segment):
* UserInterface/ScriptTimelineOverviewGraph.js: Added.
(WebInspector.ScriptTimelineOverviewGraph.prototype.reset):
(WebInspector.ScriptTimelineOverviewGraph.prototype.updateLayout):
(WebInspector.ScriptTimelineOverviewGraph.prototype._scriptTimelineRecordAdded):
* UserInterface/TimelineContentView.js:
(WebInspector.TimelineContentView.prototype._showTimelineView):
(WebInspector.TimelineContentView.prototype._update):
(WebInspector.TimelineContentView.prototype._recordingReset):
Create and keep the graphs informed.
* UserInterface/TimelineDataGridNode.js:
(WebInspector.TimelineDataGridNode):
(WebInspector.TimelineDataGridNode.prototype.refreshGraph):
Combine records that might overlap.
* UserInterface/TimelineOverview.css:
(.timeline-overview > .graphs-container):
(.timeline-overview > .graphs-container > .timeline-overview-graph):
(.timeline-overview > .graphs-container > .timeline-overview-graph:nth-child(even)):
(.timeline-overview > .graphs-container > .timeline-overview-graph:not(:first-child)):
Add the graph rows with alternating stripe.
* UserInterface/TimelineOverview.js:
(WebInspector.TimelineOverview):
(WebInspector.TimelineOverview.prototype.set startTime):
(WebInspector.TimelineOverview.prototype.get currentTime):
(WebInspector.TimelineOverview.prototype.set currentTime):
(WebInspector.TimelineOverview.prototype.updateLayout):
(WebInspector.TimelineOverview.prototype.updateLayoutIfNeeded):
Track currentTime in a member variable and let TimelineOverview manage the current time marker.
* UserInterface/TimelineOverviewGraph.js: Added.
(WebInspector.TimelineOverviewGraph):
(WebInspector.TimelineOverviewGraph.prototype.get zeroTime):
(WebInspector.TimelineOverviewGraph.prototype.set zeroTime):
(WebInspector.TimelineOverviewGraph.prototype.get startTime):
(WebInspector.TimelineOverviewGraph.prototype.set startTime):
(WebInspector.TimelineOverviewGraph.prototype.get endTime):
(WebInspector.TimelineOverviewGraph.prototype.set endTime):
(WebInspector.TimelineOverviewGraph.prototype.get currentTime):
(WebInspector.TimelineOverviewGraph.prototype.set currentTime):
(WebInspector.TimelineOverviewGraph.prototype.reset):
(WebInspector.TimelineOverviewGraph.prototype.updateLayout):
(WebInspector.TimelineOverviewGraph.prototype.updateLayoutIfNeeded):
(WebInspector.TimelineOverviewGraph.prototype.needsLayout):
* UserInterface/TimelineRecordBar.css:
(.timeline-record-bar > .segment):
(.timeline-record-bar.unfinished > .segment):
(.timeline-record-bar > .segment.inactive + .segment):
(.timeline-record-bar.timeline-record-type-network > .segment.inactive):
* UserInterface/TimelineRecordBar.js:
(WebInspector.TimelineRecordBar):
(WebInspector.TimelineRecordBar.recordsCannotBeCombined):
(WebInspector.TimelineRecordBar.prototype.get records):
(WebInspector.TimelineRecordBar.prototype.set records):
(WebInspector.TimelineRecordBar.prototype.refresh):
Make TimelineRecordBar support multiple records.
* UserInterface/TimelineRuler.css:
(.timeline-ruler > .markers):
(.timeline-ruler > .selection-handle):
(.timeline-ruler > .shaded-area):
Add some z-index values to stay above graph elements.
2014-01-16 Timothy Hatcher <timothy@apple.com>
Clean up Timelines code by using ES6 features and less global access of TimelineRecording.
......
......@@ -78,3 +78,8 @@ function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunctio
return index;
}
}
function insertObjectIntoSortedArray(value, array, compareFunction)
{
array.splice(insertionIndexForObjectInListSortedByFunction(value, array, compareFunction), 0, value);
}
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
.timeline-overview-graph.layout > .timeline-record-bar {
margin-top: 8px;
height: 20px;
}
.timeline-overview-graph.layout > .timeline-record-bar > .segment {
border-radius: 2px;
}
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.LayoutTimelineOverviewGraph = function(recording)
{
WebInspector.TimelineOverviewGraph.call(this, recording);
this.element.classList.add(WebInspector.LayoutTimelineOverviewGraph.StyleClassName);
this._layoutTimeline = recording.timelines.get(WebInspector.TimelineRecord.Type.Layout);
this._layoutTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._layoutTimelineRecordAdded, this);
this._timelineRecordBars = [];
this.reset();
};
WebInspector.LayoutTimelineOverviewGraph.StyleClassName = "layout";
WebInspector.LayoutTimelineOverviewGraph.prototype = {
constructor: WebInspector.LayoutTimelineOverviewGraph,
__proto__: WebInspector.TimelineOverviewGraph.prototype,
// Public
reset: function()
{
WebInspector.TimelineOverviewGraph.prototype.reset.call(this);
this._timelineRecordBarMap = new Map;
this.element.removeChildren();
},
updateLayout: function()
{
WebInspector.TimelineOverviewGraph.prototype.updateLayout.call(this);
var startTime = this.startTime;
var currentTime = this.currentTime;
var endTime = this.endTime;
var duration = (endTime - startTime);
var visibleWidth = this.element.offsetWidth;
var secondsPerPixel = duration / visibleWidth;
var recordBarIndex = 0;
var barRecords = [];
function createBar(barRecords)
{
var timelineRecordBar = this._timelineRecordBars[recordBarIndex];
if (!timelineRecordBar)
timelineRecordBar = this._timelineRecordBars[recordBarIndex] = new WebInspector.TimelineRecordBar;
timelineRecordBar.records = barRecords;
timelineRecordBar.refresh(this);
if (!timelineRecordBar.element.parentNode)
this.element.appendChild(timelineRecordBar.element);
++recordBarIndex;
}
for (var record of this._layoutTimeline.records) {
// If this bar is completely before the bounds of the graph, skip this record.
if (record.endTime < startTime)
continue;
// If this record is completely after the current time or end time, break out now.
// Records are sorted, so all records after this will be beyond the current or end time too.
if (record.startTime > currentTime || record.startTime > endTime)
break;
// Check if the previous record is a different type or far enough away to create the bar.
if (barRecords.length && WebInspector.TimelineRecordBar.recordsCannotBeCombined(barRecords, record, secondsPerPixel)) {
createBar.call(this, barRecords);
barRecords = [];
}
barRecords.push(record);
}
// Create the bar for the last record if needed.
if (barRecords.length)
createBar.call(this, barRecords);
// Remove the remaining unused TimelineRecordBars.
for (; recordBarIndex < this._timelineRecordBars.length; ++recordBarIndex) {
this._timelineRecordBars[recordBarIndex].records = null;
this._timelineRecordBars[recordBarIndex].element.remove();
}
},
// Private
_layoutTimelineRecordAdded: function(event)
{
this.needsLayout();
}
};
......@@ -92,6 +92,9 @@
<link rel="stylesheet" href="TimelineDataGrid.css">
<link rel="stylesheet" href="TimelineRecordBar.css">
<link rel="stylesheet" href="TimelineOverview.css">
<link rel="stylesheet" href="NetworkTimelineOverviewGraph.css">
<link rel="stylesheet" href="LayoutTimelineOverviewGraph.css">
<link rel="stylesheet" href="ScriptTimelineOverviewGraph.css">
<link rel="stylesheet" href="ProfileView.css">
<link rel="stylesheet" href="JavaScriptProfileView.css">
<link rel="stylesheet" href="CSSStyleDetailsSidebarPanel.css">
......@@ -367,6 +370,10 @@
<script src="SourceCodeTimelineTimelineDataGridNode.js"></script>
<script src="TreeOutlineDataGridSynchronizer.js"></script>
<script src="TimelineOverview.js"></script>
<script src="TimelineOverviewGraph.js"></script>
<script src="NetworkTimelineOverviewGraph.js"></script>
<script src="LayoutTimelineOverviewGraph.js"></script>
<script src="ScriptTimelineOverviewGraph.js"></script>
<script src="ProfileManager.js"></script>
<script src="ProfileType.js"></script>
<script src="ProfileView.js"></script>
......
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
.timeline-overview-graph.network {
padding-top: 2px
}
.timeline-overview-graph.network > .graph-row {
position: relative;
height: 5px;
}
.timeline-overview-graph.network > .graph-row > .bar {
position: absolute;
height: 4px;
background-color: rgb(120, 176, 225);
border: 1px solid rgb(61, 147, 200);
border-radius: 2px;
margin-top: 1px;
min-width: 3px;
}
.timeline-overview-graph.network > .graph-row > .bar.inactive {
background-color: rgb(167, 204, 237);
border-color: rgb(127, 185, 220);
}
.timeline-overview-graph.network > .graph-row > .bar.inactive,
.timeline-overview-graph.network > .graph-row > .bar.unfinished {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
border-right: none;
}
.timeline-overview-graph.network > .graph-row > .bar:not(.inactive) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
z-index: 1;
box-shadow: white 1px 0 0;
}
.timeline-overview-graph.network:nth-child(even) > .graph-row > .bar:not(.inactive) {
box-shadow: rgb(247, 247, 247) 1px 0 0;
}
/*
* Copyright (C) 2014 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.NetworkTimelineOverviewGraph = function(recording)
{
WebInspector.TimelineOverviewGraph.call(this, recording);
this.element.classList.add(WebInspector.NetworkTimelineOverviewGraph.StyleClassName);
var networkTimeline = recording.timelines.get(WebInspector.TimelineRecord.Type.Network);
networkTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
networkTimeline.addEventListener(WebInspector.Timeline.Event.TimesUpdated, this.needsLayout, this);
this.reset();
};
WebInspector.NetworkTimelineOverviewGraph.StyleClassName = "network";
WebInspector.NetworkTimelineOverviewGraph.GraphRowStyleClassName = "graph-row";
WebInspector.NetworkTimelineOverviewGraph.BarStyleClassName = "bar";
WebInspector.NetworkTimelineOverviewGraph.InactiveBarStyleClassName = "inactive";
WebInspector.NetworkTimelineOverviewGraph.UnfinishedStyleClassName = "unfinished";
WebInspector.NetworkTimelineOverviewGraph.MaximumRowCount = 6;
WebInspector.NetworkTimelineOverviewGraph.MinimumBarPaddingPixels = 5;
WebInspector.NetworkTimelineOverviewGraph.prototype = {
constructor: WebInspector.NetworkTimelineOverviewGraph,
__proto__: WebInspector.TimelineOverviewGraph.prototype,
// Public
reset: function()
{
WebInspector.TimelineOverviewGraph.prototype.reset.call(this);
this._nextDumpRow = 0;
this._timelineRecordGridRows = [];
for (var i = 0; i < WebInspector.NetworkTimelineOverviewGraph.MaximumRowCount; ++i)
this._timelineRecordGridRows.push([]);
this.element.removeChildren();
},
updateLayout: function()
{
WebInspector.TimelineOverviewGraph.prototype.updateLayout.call(this);
var startTime = this.startTime;
var currentTime = this.currentTime;
var endTime = this.endTime;
var duration = (endTime - startTime);
var visibleWidth = this.element.offsetWidth;
var secondsPerPixel = duration / visibleWidth;
function updateElementPosition(element, newPosition, property)
{
newPosition *= 100;
newPosition = newPosition.toFixed(2);
var currentPosition = parseFloat(element.style[property]).toFixed(2);
if (currentPosition !== newPosition)
element.style[property] = newPosition + "%";
}
function createBar(barElementCache, rowElement, barStartTime, barEndTime, inactive)
{
if (barStartTime > currentTime)
return;
var barElement = barElementCache.shift();
if (!barElement) {
barElement = document.createElement("div");
barElement.classList.add(WebInspector.NetworkTimelineOverviewGraph.BarStyleClassName);
}
barElement.classList.toggle(WebInspector.NetworkTimelineOverviewGraph.InactiveBarStyleClassName, inactive);
if (barEndTime >= currentTime) {
barEndTime = currentTime;
barElement.classList.add(WebInspector.NetworkTimelineOverviewGraph.UnfinishedStyleClassName);
} else
barElement.classList.remove(WebInspector.NetworkTimelineOverviewGraph.UnfinishedStyleClassName);
if (inactive) {
var newBarRightPosition = 1 - ((barEndTime - startTime) / duration);
updateElementPosition(barElement, newBarRightPosition, "right");
barElement.style.removeProperty("left");
} else {
var newBarLeftPosition = (barStartTime - startTime) / duration;
updateElementPosition(barElement, newBarLeftPosition, "left");
barElement.style.removeProperty("right");
}
var newBarWidth = ((barEndTime - barStartTime) / duration);
updateElementPosition(barElement, newBarWidth, "width");
if (!barElement.parendNode)
rowElement.appendChild(barElement);
}
for (var rowRecords of this._timelineRecordGridRows) {
var rowElement = rowRecords.__rowElement;
if (!rowElement) {
rowElement = rowRecords.__rowElement = document.createElement("div");
rowElement.className = WebInspector.NetworkTimelineOverviewGraph.GraphRowStyleClassName;
this.element.appendChild(rowElement);
}
if (!rowRecords.length)
continue;
// Save the current bar elements to reuse.
var barElementCache = Array.prototype.slice.call(rowElement.childNodes);
var inactiveStartTime = NaN;
var inactiveEndTime = NaN;
var activeStartTime = NaN;
var activeEndTime = NaN;
for (var record of rowRecords) {
if (isNaN(record.startTime))
continue;
// If this bar is completely before the bounds of the graph, skip this record.
if (record.endTime < startTime)
continue;
// If this record is completely after the current time or end time, break out now.
// Records are sorted, so all records after this will be beyond the current or end time too.
if (record.startTime > currentTime || record.startTime > endTime)
break;
// Check if the previous record is far enough away to create the inactive bar.
if (!isNaN(inactiveStartTime) && inactiveEndTime + (secondsPerPixel * WebInspector.NetworkTimelineOverviewGraph.MinimumBarPaddingPixels) <= record.startTime) {
createBar.call(this, barElementCache, rowElement, inactiveStartTime, inactiveEndTime, true);
inactiveStartTime = NaN;
inactiveEndTime = NaN;
}
// If this is a new bar, peg the start time.
if (isNaN(inactiveStartTime))
inactiveStartTime = record.startTime;
// Update the end time to be the maximum we encounter. inactiveEndTime might be NaN, so "|| 0" to prevent Math.max from returning NaN.
inactiveEndTime = Math.max(inactiveEndTime || 0, record.activeStartTime);
// Check if the previous record is far enough away to create the active bar. We also create it now if the current record has no active state time.
if (!isNaN(activeStartTime) && (activeEndTime + (secondsPerPixel * WebInspector.NetworkTimelineOverviewGraph.MinimumBarPaddingPixels) <= record.activeStartTime || isNaN(record.activeStartTime))) {
if (!isNaN(activeEndTime)) {
createBar.call(this, barElementCache, rowElement, activeStartTime, activeEndTime);
activeStartTime = NaN;
activeEndTime = NaN;
}
}
if (isNaN(record.activeStartTime))
continue;
// If this is a new bar, peg the start time.
if (isNaN(activeStartTime))
activeStartTime = record.activeStartTime;
// Update the end time to be the maximum we encounter. activeEndTime might be NaN, so "|| 0" to prevent Math.max from returning NaN.
if (!isNaN(record.endTime))
activeEndTime = Math.max(activeEndTime || 0, record.endTime);
}
// Create the inactive bar for the last record if needed.
if (!isNaN(inactiveStartTime))
createBar.call(this, barElementCache, rowElement, inactiveStartTime, inactiveEndTime || currentTime, true);
// Create the active bar for the last record if needed.
if (!isNaN(activeStartTime))
createBar.call(this, barElementCache, rowElement, activeStartTime, activeEndTime || currentTime);
// Remove any unused bar elements.
for (var barElement of barElementCache)
barElement.remove();
}
},
// Private
_networkTimelineRecordAdded: function(event)
{
var resourceTimelineRecord = event.data.record;
console.assert(resourceTimelineRecord instanceof WebInspector.ResourceTimelineRecord);
function compareByStartTime(a, b)
{
return a.startTime - b.startTime;
}