Commit ce535673 authored by timothy@apple.com's avatar timothy@apple.com

Add the start of the TimelineOverview class.

TimelineOverview currently has a time ruler and tracks the current recording time.

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

Reviewed by Joseph Pecoraro.

* UserInterface/Main.html:
* UserInterface/TimelineContentView.css:
(.content-view.timeline > .timeline-overview):
* UserInterface/TimelineContentView.js:
(WebInspector.TimelineContentView):
(WebInspector.TimelineContentView.prototype.updateLayout):
(WebInspector.TimelineContentView.prototype._update):
(WebInspector.TimelineContentView.prototype._recordingStarted):
(WebInspector.TimelineContentView.prototype._recordingStopped):
(WebInspector.TimelineContentView.prototype._recordingReset):
* UserInterface/TimelineManager.js:
(WebInspector.TimelineManager.prototype.eventRecorded.processRecord):
(WebInspector.TimelineManager.prototype.eventRecorded):
* UserInterface/TimelineMarker.js: Renamed from Source/WebInspectorUI/UserInterface/TimelineEventMarker.js.
(WebInspector.TimelineMarker):
(WebInspector.TimelineMarker.prototype.get time):
(WebInspector.TimelineMarker.prototype.set time):
(WebInspector.TimelineMarker.prototype.get type):
* UserInterface/TimelineOverview.css: Added.
(.timeline-overview > .scroll-container):
(.timeline-overview > .scroll-container > .timeline-ruler):
* UserInterface/TimelineOverview.js: Added.
(WebInspector.TimelineOverview):
(WebInspector.TimelineOverview.prototype.get element):
(WebInspector.TimelineOverview.prototype.get startTime):
(WebInspector.TimelineOverview.prototype.set startTime):
(WebInspector.TimelineOverview.prototype.get secondsPerPixel):
(WebInspector.TimelineOverview.prototype.set secondsPerPixel):
(WebInspector.TimelineOverview.prototype.get endTime):
(WebInspector.TimelineOverview.prototype.set endTime):
(WebInspector.TimelineOverview.prototype.addMarker):
(WebInspector.TimelineOverview.prototype.revealMarker):
(WebInspector.TimelineOverview.prototype.updateLayout):
(WebInspector.TimelineOverview.prototype._updateElementWidth):
(WebInspector.TimelineOverview.prototype._needsLayout):
* UserInterface/TimelineRecording.js:
(WebInspector.TimelineRecording.prototype.get startTime):
(WebInspector.TimelineRecording.prototype.get endTime):
(WebInspector.TimelineRecording.prototype.reset):
* UserInterface/TimelineRuler.css:
(.timeline-ruler > .markers):
(.timeline-ruler > .markers > .marker):
(.timeline-ruler > .markers > .marker.current-time):
(.timeline-ruler > .markers > .marker.current-time::before):
(.timeline-ruler > .markers > .marker.load-event):
(.timeline-ruler > .markers > .marker.dom-content-event):
(.timeline-ruler > .markers > .marker.timestamp):
* UserInterface/TimelineRuler.js:
(WebInspector.TimelineRuler):
(WebInspector.TimelineRuler.prototype.updateLayout):
(WebInspector.TimelineRuler.prototype._needsLayout):
(WebInspector.TimelineRuler.prototype._needsMarkerLayout.update):
(WebInspector.TimelineRuler.prototype._needsMarkerLayout):
(WebInspector.TimelineRuler.prototype._recalculate):
(WebInspector.TimelineRuler.prototype._updateLeftPositionOfElement):
(WebInspector.TimelineRuler.prototype._updateMarkers):
(WebInspector.TimelineRuler.prototype._timelineMarkerTimeChanged):

git-svn-id: http://svn.webkit.org/repository/webkit/trunk@162408 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 8b8175d8
2013-12-17 Timothy Hatcher <timothy@apple.com>
Add the start of the TimelineOverview class.
TimelineOverview currently has a time ruler and tracks the current recording time.
https://bugs.webkit.org/show_bug.cgi?id=125878
Reviewed by Joseph Pecoraro.
* UserInterface/Main.html:
* UserInterface/TimelineContentView.css:
(.content-view.timeline > .timeline-overview):
* UserInterface/TimelineContentView.js:
(WebInspector.TimelineContentView):
(WebInspector.TimelineContentView.prototype.updateLayout):
(WebInspector.TimelineContentView.prototype._update):
(WebInspector.TimelineContentView.prototype._recordingStarted):
(WebInspector.TimelineContentView.prototype._recordingStopped):
(WebInspector.TimelineContentView.prototype._recordingReset):
* UserInterface/TimelineManager.js:
(WebInspector.TimelineManager.prototype.eventRecorded.processRecord):
(WebInspector.TimelineManager.prototype.eventRecorded):
* UserInterface/TimelineMarker.js: Renamed from Source/WebInspectorUI/UserInterface/TimelineEventMarker.js.
(WebInspector.TimelineMarker):
(WebInspector.TimelineMarker.prototype.get time):
(WebInspector.TimelineMarker.prototype.set time):
(WebInspector.TimelineMarker.prototype.get type):
* UserInterface/TimelineOverview.css: Added.
(.timeline-overview > .scroll-container):
(.timeline-overview > .scroll-container > .timeline-ruler):
* UserInterface/TimelineOverview.js: Added.
(WebInspector.TimelineOverview):
(WebInspector.TimelineOverview.prototype.get element):
(WebInspector.TimelineOverview.prototype.get startTime):
(WebInspector.TimelineOverview.prototype.set startTime):
(WebInspector.TimelineOverview.prototype.get secondsPerPixel):
(WebInspector.TimelineOverview.prototype.set secondsPerPixel):
(WebInspector.TimelineOverview.prototype.get endTime):
(WebInspector.TimelineOverview.prototype.set endTime):
(WebInspector.TimelineOverview.prototype.addMarker):
(WebInspector.TimelineOverview.prototype.revealMarker):
(WebInspector.TimelineOverview.prototype.updateLayout):
(WebInspector.TimelineOverview.prototype._updateElementWidth):
(WebInspector.TimelineOverview.prototype._needsLayout):
* UserInterface/TimelineRecording.js:
(WebInspector.TimelineRecording.prototype.get startTime):
(WebInspector.TimelineRecording.prototype.get endTime):
(WebInspector.TimelineRecording.prototype.reset):
* UserInterface/TimelineRuler.css:
(.timeline-ruler > .markers):
(.timeline-ruler > .markers > .marker):
(.timeline-ruler > .markers > .marker.current-time):
(.timeline-ruler > .markers > .marker.current-time::before):
(.timeline-ruler > .markers > .marker.load-event):
(.timeline-ruler > .markers > .marker.dom-content-event):
(.timeline-ruler > .markers > .marker.timestamp):
* UserInterface/TimelineRuler.js:
(WebInspector.TimelineRuler):
(WebInspector.TimelineRuler.prototype.updateLayout):
(WebInspector.TimelineRuler.prototype._needsLayout):
(WebInspector.TimelineRuler.prototype._needsMarkerLayout.update):
(WebInspector.TimelineRuler.prototype._needsMarkerLayout):
(WebInspector.TimelineRuler.prototype._recalculate):
(WebInspector.TimelineRuler.prototype._updateLeftPositionOfElement):
(WebInspector.TimelineRuler.prototype._updateMarkers):
(WebInspector.TimelineRuler.prototype._timelineMarkerTimeChanged):
2013-12-13 Timothy Hatcher <timothy@apple.com>
Clean up and refactor TimelineDecorations into TimelineRuler.
......
......@@ -194,6 +194,7 @@
<script src="SourceCodeTimeline.js"></script>
<script src="TimelineRecord.js"></script>
<script src="TimelineEventMarker.js"></script>
<script src="TimelineMarker.js"></script>
<script src="ResourceTimelineRecord.js"></script>
<script src="FrameResourceManager.js"></script>
<script src="IssueManager.js"></script>
......
......@@ -23,6 +23,14 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
.content-view.timeline > .timeline-overview {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 130px;
}
.content-view.timeline > .view-container {
position: absolute;
top: 130px;
......
......@@ -29,6 +29,12 @@ WebInspector.TimelineContentView = function(recording)
this.element.classList.add(WebInspector.TimelineContentView.StyleClassName);
this._timelineOverview = new WebInspector.TimelineOverview;
this.element.appendChild(this._timelineOverview.element);
this._currentTimeMarker = new WebInspector.TimelineMarker(0, WebInspector.TimelineMarker.Type.CurrentTime);
this._timelineOverview.addMarker(this._currentTimeMarker);
this._viewContainer = document.createElement("div");
this._viewContainer.classList.add(WebInspector.TimelineContentView.ViewContainerStyleClassName);
this.element.appendChild(this._viewContainer);
......@@ -65,7 +71,12 @@ WebInspector.TimelineContentView = function(recording)
this._currentTimelineView = null;
this._currentTimelineViewIdentifier = null;
this._updating = false;
this._lastUpdateTimestamp = NaN;
WebInspector.timelineManager.recording.addEventListener(WebInspector.TimelineRecording.Event.Reset, this._recordingReset, this);
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.RecordingStarted, this._recordingStarted, this);
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.RecordingStopped, this._recordingStopped, this);
this.showOverviewTimelineView();
};
......@@ -129,6 +140,8 @@ WebInspector.TimelineContentView.prototype = {
updateLayout: function()
{
this._timelineOverview.updateLayout();
if (!this._currentTimelineView)
return;
......@@ -168,8 +181,60 @@ WebInspector.TimelineContentView.prototype = {
this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
},
_update: function(timestamp)
{
var startTime = WebInspector.timelineManager.recording.startTime;
var currentTime = this._currentTimeMarker.time || startTime;
var endTime = WebInspector.timelineManager.recording.endTime;
var timespanSinceLastUpdate = (timestamp - this._lastUpdateTimestamp) / 1000 || 0;
currentTime += timespanSinceLastUpdate;
this._currentTimeMarker.time = currentTime;
this._timelineOverview.startTime = startTime;
this._timelineOverview.endTime = Math.max(endTime, currentTime);
// Force a layout now since we are already in an animation frame and don't need to delay it until the next.
this._timelineOverview.updateLayout();
this._timelineOverview.revealMarker(this._currentTimeMarker);
// Only stop updating if the current time is greater than the end time.
if (!this._updating && currentTime >= endTime) {
this._lastUpdateTimestamp = NaN;
return;
}
this._lastUpdateTimestamp = timestamp;
requestAnimationFrame(this._updateCallback);
},
_recordingStarted: function(event)
{
console.assert(!this._updating);
if (this._updating)
return;
this._updating = true;
if (!this._updateCallback)
this._updateCallback = this._update.bind(this);
requestAnimationFrame(this._updateCallback);
},
_recordingStopped: function(event)
{
console.assert(this._updating);
this._updating = false;
},
_recordingReset: function(event)
{
this._currentTimeMarker.time = 0;
this._overviewTimelineView.reset();
for (var identifier in this._discreteTimelineViewMap)
......
......@@ -135,7 +135,7 @@ WebInspector.TimelineManager.prototype = {
if (!frame.isMainFrame())
break;
var eventMarker = new WebInspector.TimelineEventMarker(startTime, WebInspector.TimelineEventMarker.Type.LoadEvent);
var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.LoadEvent);
this._recording.addEventMarker(eventMarker);
this._stopAutoRecordingSoon();
......@@ -154,7 +154,7 @@ WebInspector.TimelineManager.prototype = {
if (!frame.isMainFrame())
break;
var eventMarker = new WebInspector.TimelineEventMarker(startTime, WebInspector.TimelineEventMarker.Type.DOMContentEvent);
var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.DOMContentEvent);
this._recording.addEventMarker(eventMarker);
break;
......@@ -219,7 +219,7 @@ WebInspector.TimelineManager.prototype = {
break;
case TimelineAgent.EventType.TimeStamp:
var eventMarker = new WebInspector.TimelineEventMarker(startTime, WebInspector.TimelineEventMarker.Type.TimeStamp);
var eventMarker = new WebInspector.TimelineMarker(startTime, WebInspector.TimelineMarker.Type.TimeStamp);
this._recording.addEventMarker(eventMarker);
break;
......
......@@ -23,31 +23,46 @@
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.TimelineEventMarker = function(timestamp, type)
WebInspector.TimelineMarker = function(time, type)
{
WebInspector.Object.call(this);
console.assert(timestamp);
console.assert(type);
this._timestamp = timestamp;
this._time = time || 0;
this._type = type;
};
WebInspector.TimelineEventMarker.Type = {
WebInspector.TimelineMarker.Event = {
TimeChanged: "timeline-marker-time-changed"
};
WebInspector.TimelineMarker.Type = {
CurrentTime: "current-time",
LoadEvent: "load-event",
DOMContentEvent: "dom-content-event",
TimeStamp: "timestamp"
};
WebInspector.TimelineEventMarker.prototype = {
constructor: WebInspector.TimelineEventMarker,
WebInspector.TimelineMarker.prototype = {
constructor: WebInspector.TimelineMarker,
__proto__: WebInspector.Object.prototype,
// Public
get timestamp()
get time()
{
return this._time;
},
set time(x)
{
return this._timestamp;
if (this._time === x)
return;
this._time = x || 0;
this.dispatchEventToListeners(WebInspector.TimelineMarker.Event.TimeChanged);
},
get type()
......@@ -55,5 +70,3 @@ WebInspector.TimelineEventMarker.prototype = {
return this._type;
}
};
WebInspector.TimelineEventMarker.prototype.__proto__ = WebInspector.Object.prototype;
/*
* Copyright (C) 2013 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 > .scroll-container {
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
overflow-x: auto;
overflow-y: hidden;
}
.timeline-overview > .scroll-container > .timeline-ruler {
position: absolute;
top: 0;
left: 0;
bottom: 0;
min-width: 100%;
overflow: hidden;
}
/*
* Copyright (C) 2013 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.TimelineOverview = function()
{
WebInspector.Object.call(this);
this._element = document.createElement("div");
this._element.className = WebInspector.TimelineOverview.StyleClassName;
this._scrollContainer = document.createElement("div");
this._scrollContainer.className = WebInspector.TimelineOverview.ScrollContainerStyleClassName;
this._element.appendChild(this._scrollContainer);
this._timelineRuler = new WebInspector.TimelineRuler;
this._timelineRuler.allowsClippedLabels = true;
this._scrollContainer.appendChild(this._timelineRuler.element);
this._endTime = 0;
this.startTime = 0;
this.secondsPerPixel = 0.0025;
};
WebInspector.TimelineOverview.StyleClassName = "timeline-overview";
WebInspector.TimelineOverview.ScrollContainerStyleClassName = "scroll-container";
WebInspector.TimelineOverview.prototype = {
constructor: WebInspector.TimelineOverview,
__proto__: WebInspector.Object.prototype,
// Public
get element()
{
return this._element;
},
get startTime()
{
return this._timelineRuler.startTime;
},
set startTime(x)
{
if (this._timelineRuler.startTime === x)
return;
this._timelineRuler.zeroTime = x;
this._timelineRuler.startTime = x;
this._needsLayout();
},
get secondsPerPixel()
{
return this._timelineRuler.secondsPerPixel;
},
set secondsPerPixel(x)
{
if (this._timelineRuler.secondsPerPixel === x)
return;
this._timelineRuler.secondsPerPixel = x;
this._needsLayout();
},
get endTime()
{
return this._endTime;
},
set endTime(x)
{
if (this._endTime === x)
return;
this._endTime = x || 0;
this._needsLayout();
},
addMarker: function(marker)
{
this._timelineRuler.addMarker(marker);
},
revealMarker: function(marker)
{
var markerElement = this._timelineRuler.elementForMarker(marker);
if (!markerElement)
return;
markerElement.scrollIntoViewIfNeeded(true);
},
updateLayout: function()
{
if (this._scheduledLayoutUpdateIdentifier) {
cancelAnimationFrame(this._scheduledLayoutUpdateIdentifier);
delete this._scheduledLayoutUpdateIdentifier;
}
// Calculate the required width based on the duration and seconds per pixel.
var duration = this.endTime - this.startTime;
var newWidth = Math.ceil(duration / this.secondsPerPixel);
// Update all relevant elements to the new required width.
this._updateElementWidth(this._timelineRuler.element, newWidth);
// Update the time ruler layout now that its width has changed.
this._timelineRuler.updateLayout();
},
// Private
_updateElementWidth: function(element, newWidth)
{
var currentWidth = parseFloat(element.style.width).toFixed(0);
if (currentWidth !== newWidth)
element.style.width = newWidth + "px";
},
_needsLayout: function()
{
if (this._scheduledLayoutUpdateIdentifier)
return;
this._scheduledLayoutUpdateIdentifier = requestAnimationFrame(this.updateLayout.bind(this));
}
};
......@@ -47,6 +47,16 @@ WebInspector.TimelineRecording.prototype = {
return this._timelines;
},
get startTime()
{
return this._startTime;
},
get endTime()
{
return this._endTime;
},
reset: function(newObject)
{
if (this._timelines) {
......@@ -66,6 +76,8 @@ WebInspector.TimelineRecording.prototype = {
this._sourceCodeTimelinesMap = new Map;
this._eventMarkers = [];
this._startTime = NaN;
this._endTime = NaN;
if (!newObject)
this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.Reset);
......
......@@ -55,44 +55,63 @@
white-space: nowrap;
}
.timeline-ruler > .event-markers {
.timeline-ruler > .markers {
position: absolute;
top: 22px;
left: 0;
right: 0;
bottom: 0;
z-index: 1;
}
.timeline-ruler > .event-markers > .event-marker-tooltip {
.timeline-ruler > .markers > .divider {
position: absolute;
top: 0;
width: 1px;
top: 1px;
bottom: 0;
width: 9px;
pointer-events: auto;
-webkit-transform: translateX(-1px);
background-color: rgba(0, 0, 0, 0.05);
}
.timeline-ruler > .event-markers > .event-marker {
.timeline-ruler > .markers > .marker {
position: absolute;
top: 0;
bottom: 0;
margin-left: 4px;
-webkit-transform: translateX(-1px);
border-left-width: 1px;
border-left-style: dashed;
border-left-color: rgba(128, 128, 128, 0.5);
}
.timeline-ruler > .event-markers > .event-marker.load-event {
.timeline-ruler > .markers > .marker.current-time {
border-left-color: red;
border-left-style: solid;
}
.timeline-ruler > .markers > .marker.current-time::before {
position: absolute;
top: -5px;
left: -5px;
width: 9px;
height: 9px;
border-radius: 5px;
background-color: red;
content: "";
}
.timeline-ruler > .markers > .marker.load-event {
border-left-color: rgba(255, 0, 0, 0.5);
}
.timeline-ruler > .event-markers > .event-marker.dom-content-event {
.timeline-ruler > .markers > .marker.dom-content-event {
border-left-color: rgba(0, 0, 255, 0.5);
}
.timeline-ruler > .event-markers > .event-marker.timestamp {
.timeline-ruler > .markers > .marker.timestamp {
border-left-color: rgba(0, 110, 0, 0.5);
}
......@@ -35,7 +35,7 @@ WebInspector.TimelineRuler = function()
this._element.appendChild(this._headerElement);
this._markersElement = document.createElement("div");
this._markersElement.className = WebInspector.TimelineRuler.EventMarkersElementStyleClassName;
this._markersElement.className = WebInspector.TimelineRuler.MarkersElementStyleClassName;
this._element.appendChild(this._markersElement);
this._zeroTime = 0;
......@@ -45,6 +45,8 @@ WebInspector.TimelineRuler = function()
this._secondsPerPixel = 0;
this._endTimePinned = false;
this._allowsClippedLabels = false;
this._markerElementMap = new Map;
}
WebInspector.TimelineRuler.MinimumLeftDividerSpacing = 48;
......@@ -55,9 +57,8 @@ WebInspector.TimelineRuler.HeaderElementStyleClassName = "header";
WebInspector.TimelineRuler.DividerElementStyleClassName = "divider";
WebInspector.TimelineRuler.DividerLabelElementStyleClassName = "label";
WebInspector.TimelineRuler.EventMarkersElementStyleClassName = "event-markers";
WebInspector.TimelineRuler.EventMarkerTooltipElementStyleClassName = "event-marker-tooltip";
WebInspector.TimelineRuler.BaseEventMarkerElementStyleClassName = "event-marker";
WebInspector.TimelineRuler.MarkersElementStyleClassName = "markers";
WebInspector.TimelineRuler.BaseMarkerElementStyleClassName = "marker";
WebInspector.TimelineRuler.prototype = {
constructor: WebInspector.TimelineRuler,
......@@ -182,6 +183,29 @@ WebInspector.TimelineRuler.prototype = {
this._needsLayout();
},
addMarker: function(marker)
{
console.assert(marker instanceof WebInspector.TimelineMarker);
if (this._markerElementMap.has(marker))
return;
marker.addEventListener(WebInspector.TimelineMarker.Event.TimeChanged, this._timelineMarkerTimeChanged, this);
var markerElement = document.createElement("div");
markerElement.classList.add(WebInspector.TimelineRuler.BaseMarkerElementStyleClassName);
markerElement.classList.add(marker.type);
this._markerElementMap.set(marker, markerElement);
this._needsMarkerLayout();
},
elementForMarker: function(marker)
{
return this._markerElementMap.get(marker) || null;
},
updateLayout: function()
{
if (this._scheduledLayoutUpdateIdentifier) {
......@@ -227,6 +251,8 @@ WebInspector.TimelineRuler.prototype = {
if (!this._endTimePinned)
++dividerCount;
var markerDividers = this._markersElement.querySelectorAll("." + WebInspector.TimelineRuler.DividerElementStyleClassName);
var dividerElement = this._headerElement.firstChild;
for (var i = 0; i <= dividerCount; ++i) {
......@@ -241,6 +267,13 @@ WebInspector.TimelineRuler.prototype = {
dividerElement.appendChild(labelElement);
}
var markerDividerElement = markerDividers[i];
if (!markerDividerElement) {
markerDividerElement = document.createElement("div");
markerDividerElement.className = WebInspector.TimelineRuler.DividerElementStyleClassName;
this._markersElement.appendChild(markerDividerElement);
}
var dividerTime = firstDividerTime + (sliceTime * i);
var newLeftPosition = (dividerTime - this._startTime) / duration;
......@@ -259,18 +292,10 @@ WebInspector.TimelineRuler.prototype = {
continue;
}
if (this._endTimePinned)
newLeftPosition *= 100;
else
newLeftPosition *= visibleWidth;
newLeftPosition = newLeftPosition.toFixed(2);
var currentLeftPosition = parseFloat(dividerElement.style.left).toFixed(2);
if (currentLeftPosition !== newLeftPosition)
dividerElement.style.left = newLeftPosition + (this._endTimePinned ? "%" : "px");
this._updateLeftPositionOfElement(dividerElement, newLeftPosition, visibleWidth);
this._updateLeftPositionOfElement(markerDividerElement, newLeftPosition, visibleWidth);
dividerElement._labelElement.textContent = isNaN(dividerTime) ? "" : Number.secondsToString(dividerTime, true);
dividerElement._labelElement.textContent = isNaN(dividerTime) ? "" : Number.secondsToString(dividerTime - this._zeroTime, true);
dividerElement = dividerElement.nextSibling;
}
......@@ -280,6 +305,11 @@ WebInspector.TimelineRuler.prototype = {
dividerElement.remove();
dividerElement = nextDividerElement;
}
for (; i < markerDividers.length; ++i)
markerDividers[i].remove();
this._updateMarkers(visibleWidth, duration);
},
// Private
......@@ -288,9 +318,38 @@ WebInspector.TimelineRuler.prototype = {
{
if (this._scheduledLayoutUpdateIdentifier)
return;
if (this._scheduledMarkerLayoutUpdateIdentifier) {
cancelAnimationFrame(this._scheduledMarkerLayoutUpdateIdentifier);
delete this._scheduledMarkerLayoutUpdateIdentifier;