Web Inspector: add a separate overview for the Rendering Frames timeline
authorcommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2015 13:30:22 +0000 (13:30 +0000)
committercommit-queue@webkit.org <commit-queue@webkit.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Apr 2015 13:30:22 +0000 (13:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=144245

Patch by Matt Baker <mattbaker@apple.com> on 2015-04-28
Reviewed by Timothy Hatcher.

The Timelines tab now supports two view modes, labeled "Timelines" and "Rendering Frames", with each mode
having a seperate timeline overview and selected range. The Timelines mode displays the original time-based
graphs (Network, Layout, and Script), and switching to the Rendering Frames mode displays a frames graph
with a timeline ruler which shows frame indices.

If the rendering frames timeline is supported by the backend, a navigation bar is added to the timelines
sidebar with controls for switching between view modes. In addition to user-triggered view mode changes, the
timelines sidebar will automatically change the current view mode in response to content view changes that
are triggered elsewhere in the UI (for example, when a timeline that does not belong to the current view
mode is selected via the navigation path).

* UserInterface/Controllers/TimelineManager.js:
(WebInspector.TimelineManager.prototype.get activeRecording): Deleted.
(WebInspector.TimelineManager.prototype.get recordings): Deleted.
Removed unused code.

* UserInterface/Main.html:
New files.

* UserInterface/Models/RenderingFrameTimelineRecord.js:
(WebInspector.RenderingFrameTimelineRecord):
(WebInspector.RenderingFrameTimelineRecord.resetFrameIndex):
(WebInspector.RenderingFrameTimelineRecord.prototype.get frameIndex):
(WebInspector.RenderingFrameTimelineRecord.prototype.get frameNumber):
* UserInterface/Models/TimelineRecording.js:
(WebInspector.TimelineRecording.prototype.reset):
Frame number is now derived from frame index.

* UserInterface/Views/LinearTimelineOverview.js:
(WebInspector.LinearTimelineOverview):
(WebInspector.LinearTimelineOverview.prototype.canShowTimeline):
New overview class for time-based timeline graphs.

* UserInterface/Views/RenderingFrameDetailsSidebarPanel.js:
(WebInspector.RenderingFrameDetailsSidebarPanel):
(WebInspector.RenderingFrameDetailsSidebarPanel.prototype.updateRangeSelection):
(WebInspector.RenderingFrameDetailsSidebarPanel.prototype._getSelectedRecords):
Changed type of selected range from time to frame indices.

* UserInterface/Views/RenderingFrameTimelineOverview.js:
(WebInspector.RenderingFrameTimelineOverview.this.timelineRuler.formatLabelCallback):
(WebInspector.RenderingFrameTimelineOverview):
(WebInspector.RenderingFrameTimelineOverview.prototype.canShowTimeline):
New overview class for frame-based timeline graphs.

* UserInterface/Views/RenderingFrameTimelineOverviewGraph.css:
(.timeline-overview > .graphs-container > .timeline-overview-graph.rendering-frame):
* UserInterface/Views/RenderingFrameTimelineOverviewGraph.js:
(WebInspector.RenderingFrameTimelineOverviewGraph):
(WebInspector.RenderingFrameTimelineOverviewGraph.prototype._updateDividers.createDividerAtPosition.get if):
Updated to use frame index ruler and removed frame combining logic.

* UserInterface/Views/RenderingFrameTimelineView.js:
(WebInspector.RenderingFrameTimelineView):
Increased column widths.

* UserInterface/Views/TimelineOverview.css:
(.timeline-overview > .graphs-container):
(body.mac-platform.legacy .timeline-overview > .graphs-container):
Updated for new ruler height.

* UserInterface/Views/TimelineOverview.js:
(WebInspector.TimelineOverview):
(WebInspector.TimelineOverview.prototype.get secondsPerPixel):
(WebInspector.TimelineOverview.prototype.set secondsPerPixel):
(WebInspector.TimelineOverview.prototype.get visibleDuration):
(WebInspector.TimelineOverview.prototype.set selectionDuration):
(WebInspector.TimelineOverview.prototype.updateLayout):
(WebInspector.TimelineOverview.prototype.get timelineRuler):
(WebInspector.TimelineOverview.prototype.canShowTimeline):
(WebInspector.TimelineOverview.prototype._handleScrollEvent):
(WebInspector.TimelineOverview.prototype._handleWheelEvent):
(WebInspector.TimelineOverview.prototype._timelineRemoved):
(WebInspector.TimelineOverview.prototype._timeRangeSelectionChanged):
(WebInspector.TimelineOverview.prototype.set currentTime): Deleted.
(WebInspector.TimelineOverview.prototype.updateLayoutIfNeeded): Deleted.
(WebInspector.TimelineOverview.prototype._needsLayout): Deleted.
Converted to base class. Derived classes provide settings and permitted timeline types.

* UserInterface/Views/TimelineRecordFrame.css:
(.timeline-record-frame):
(.timeline-record-frame > .frame):
(.timeline-record-frame > .frame > .duration):
(.timeline-record-frame > .frame > .duration.timeline-record-type-network):
(.timeline-record-frame > .frame > .duration.timeline-record-type-layout):
(.timeline-record-frame > .frame > .duration.timeline-record-type-script):
(.timeline-record-frame > .frame > .duration:last-child): Deleted.
New graph frames styles.

* UserInterface/Views/TimelineRecordFrame.js:
(WebInspector.TimelineRecordFrame):
(WebInspector.TimelineRecordFrame.prototype.get record):
(WebInspector.TimelineRecordFrame.prototype.set record):
(WebInspector.TimelineRecordFrame.prototype._updateChildElements.createDurationElement):
(WebInspector.TimelineRecordFrame.prototype.get element): Deleted.
Updated to use frame index ruler.
Removed dropped frames and frame combining logic.

* UserInterface/Views/TimelineRecordingContentView.js:
(WebInspector.TimelineRecordingContentView):
(WebInspector.TimelineRecordingContentView.prototype.shown):
(WebInspector.TimelineRecordingContentView.prototype.hidden):
(WebInspector.TimelineRecordingContentView.prototype.updateLayout):
(WebInspector.TimelineRecordingContentView.prototype._currentContentViewDidChange):
(WebInspector.TimelineRecordingContentView.prototype._updateTimes):
(WebInspector.TimelineRecordingContentView.prototype._updateTimelineOverviewHeight):
(WebInspector.TimelineRecordingContentView.prototype._getRenderingFrameTimeline):
(WebInspector.TimelineRecordingContentView.prototype._timelineRemoved):
(WebInspector.TimelineRecordingContentView.prototype._timelineCountChanged):
(WebInspector.TimelineRecordingContentView.prototype._recordingReset):
(WebInspector.TimelineRecordingContentView.prototype._timeRangeSelectionChanged):
(WebInspector.TimelineRecordingContentView.prototype.get currentTimelineView): Deleted.
(WebInspector.TimelineRecordingContentView.prototype.goForward): Deleted.
(WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
(WebInspector.TimelineRecordingContentView.prototype._contentViewSupplementalRepresentedObjectsDidChange): Deleted.
(WebInspector.TimelineRecordingContentView.prototype._update): Deleted.
(WebInspector.TimelineRecordingContentView.prototype._debuggerPaused): Deleted.
(WebInspector.TimelineRecordingContentView.prototype._debuggerResumed): Deleted.
(WebInspector.TimelineRecordingContentView.prototype._recordingTimesUpdated): Deleted.
Maintains two timeline overviews, switching between them based on the current content view.
Updated tree element filtering to support both overview rulers.

* UserInterface/Views/TimelineRuler.css:
(.timeline-ruler > .header):
(body.mac-platform.legacy .timeline-ruler > .header):
(.timeline-ruler > .header > .divider > .label):
(.timeline-ruler > .selection-drag):
(body.mac-platform.legacy .timeline-ruler > .selection-drag):
(.timeline-ruler > .selection-handle):
(body.mac-platform.legacy .timeline-ruler > .selection-handle):
(.timeline-ruler > .header > .divider): Deleted.
(.timeline-ruler > .selection-drag:active): Deleted.
Updated for new ruler height.

* UserInterface/Views/TimelineRuler.js:
(WebInspector.TimelineRuler):
(WebInspector.TimelineRuler.prototype.set formatLabelCallback):
(WebInspector.TimelineRuler.prototype.updateLayout):
(WebInspector.TimelineRuler.prototype._formatDividerLabelText):
(WebInspector.TimelineRuler.prototype.set allowsClippedLabels): Deleted.
(WebInspector.TimelineRuler.prototype._updateSelection): Deleted.
Added ability to customize label formatting.

* UserInterface/Views/TimelineSidebarPanel.css:
(.panel.timeline .navigation-bar.timelines-view):
(.sidebar > .panel.navigation.timeline > .title-bar):
(body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar):
(.sidebar > .panel.navigation.timeline > .title-bar.timelines):
(.sidebar > .panel.navigation.timeline > .navigation-bar-container):
(.sidebar > .panel.navigation.timeline > .navigation-bar-container > .navigation-bar):
(.sidebar > .panel.navigation.timeline > .title-bar.timeline-events):
(body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar.timeline-events):
(.sidebar > .panel.navigation.timeline > .timelines-content):
(.sidebar > .panel.navigation.timeline > .empty-content-placeholder):
(body.mac-platform.legacy .sidebar > .panel.navigation.timeline > :matches(.content, .empty-content-placeholder)):
(.sidebar > .panel.navigation.timeline > .timelines-content li.item.selected + li.item): Deleted.
(body.window-inactive .sidebar > .panel.navigation.timeline > .timelines-content li.item.selected + li.item): Deleted.
Updated for new navigation bar and ruler height.

* UserInterface/Views/TimelineSidebarPanel.js:
(WebInspector.TimelineSidebarPanel):
(WebInspector.TimelineSidebarPanel.prototype.get viewMode):
(WebInspector.TimelineSidebarPanel.prototype.canShowTimeline):
(WebInspector.TimelineSidebarPanel.showTimelineViewForTimeline.this._timelineTreeElementMap.get select):
(WebInspector.TimelineSidebarPanel.get this):
(WebInspector.TimelineSidebarPanel._timelineAdded.set this):
Added support for two view modes: Timelines and Rendering Frames.

* WebInspectorUI.vcxproj/WebInspectorUI.vcxproj:
* WebInspectorUI.vcxproj/WebInspectorUI.vcxproj.filters:
New files.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@183469 268f45cc-cd09-0410-ab3c-d52691b4dbfc

22 files changed:
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Controllers/TimelineManager.js
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Models/RenderingFrameTimelineRecord.js
Source/WebInspectorUI/UserInterface/Models/TimelineRecording.js
Source/WebInspectorUI/UserInterface/Views/LinearTimelineOverview.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/RenderingFrameDetailsSidebarPanel.js
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverview.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.css
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverviewGraph.js
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js
Source/WebInspectorUI/UserInterface/Views/TimelineOverview.css
Source/WebInspectorUI/UserInterface/Views/TimelineOverview.js
Source/WebInspectorUI/UserInterface/Views/TimelineRecordFrame.css
Source/WebInspectorUI/UserInterface/Views/TimelineRecordFrame.js
Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js
Source/WebInspectorUI/UserInterface/Views/TimelineRuler.css
Source/WebInspectorUI/UserInterface/Views/TimelineRuler.js
Source/WebInspectorUI/UserInterface/Views/TimelineSidebarPanel.css
Source/WebInspectorUI/UserInterface/Views/TimelineSidebarPanel.js
Source/WebInspectorUI/WebInspectorUI.vcxproj/WebInspectorUI.vcxproj
Source/WebInspectorUI/WebInspectorUI.vcxproj/WebInspectorUI.vcxproj.filters

index ff074a8..26b3aba 100644 (file)
@@ -1,3 +1,182 @@
+2015-04-28  Matt Baker  <mattbaker@apple.com>
+
+        Web Inspector: add a separate overview for the Rendering Frames timeline
+        https://bugs.webkit.org/show_bug.cgi?id=144245
+
+        Reviewed by Timothy Hatcher.
+
+        The Timelines tab now supports two view modes, labeled "Timelines" and "Rendering Frames", with each mode
+        having a seperate timeline overview and selected range. The Timelines mode displays the original time-based
+        graphs (Network, Layout, and Script), and switching to the Rendering Frames mode displays a frames graph
+        with a timeline ruler which shows frame indices.
+
+        If the rendering frames timeline is supported by the backend, a navigation bar is added to the timelines
+        sidebar with controls for switching between view modes. In addition to user-triggered view mode changes, the
+        timelines sidebar will automatically change the current view mode in response to content view changes that
+        are triggered elsewhere in the UI (for example, when a timeline that does not belong to the current view
+        mode is selected via the navigation path).
+
+        * UserInterface/Controllers/TimelineManager.js:
+        (WebInspector.TimelineManager.prototype.get activeRecording): Deleted.
+        (WebInspector.TimelineManager.prototype.get recordings): Deleted.
+        Removed unused code.
+
+        * UserInterface/Main.html:
+        New files.
+
+        * UserInterface/Models/RenderingFrameTimelineRecord.js:
+        (WebInspector.RenderingFrameTimelineRecord):
+        (WebInspector.RenderingFrameTimelineRecord.resetFrameIndex):
+        (WebInspector.RenderingFrameTimelineRecord.prototype.get frameIndex):
+        (WebInspector.RenderingFrameTimelineRecord.prototype.get frameNumber):
+        * UserInterface/Models/TimelineRecording.js:
+        (WebInspector.TimelineRecording.prototype.reset):
+        Frame number is now derived from frame index.
+
+        * UserInterface/Views/LinearTimelineOverview.js:
+        (WebInspector.LinearTimelineOverview):
+        (WebInspector.LinearTimelineOverview.prototype.canShowTimeline):
+        New overview class for time-based timeline graphs.
+
+        * UserInterface/Views/RenderingFrameDetailsSidebarPanel.js:
+        (WebInspector.RenderingFrameDetailsSidebarPanel):
+        (WebInspector.RenderingFrameDetailsSidebarPanel.prototype.updateRangeSelection):
+        (WebInspector.RenderingFrameDetailsSidebarPanel.prototype._getSelectedRecords):
+        Changed type of selected range from time to frame indices.
+
+        * UserInterface/Views/RenderingFrameTimelineOverview.js:
+        (WebInspector.RenderingFrameTimelineOverview.this.timelineRuler.formatLabelCallback):
+        (WebInspector.RenderingFrameTimelineOverview):
+        (WebInspector.RenderingFrameTimelineOverview.prototype.canShowTimeline):
+        New overview class for frame-based timeline graphs.
+
+        * UserInterface/Views/RenderingFrameTimelineOverviewGraph.css:
+        (.timeline-overview > .graphs-container > .timeline-overview-graph.rendering-frame):
+        * UserInterface/Views/RenderingFrameTimelineOverviewGraph.js:
+        (WebInspector.RenderingFrameTimelineOverviewGraph):
+        (WebInspector.RenderingFrameTimelineOverviewGraph.prototype._updateDividers.createDividerAtPosition.get if):
+        Updated to use frame index ruler and removed frame combining logic.
+
+        * UserInterface/Views/RenderingFrameTimelineView.js:
+        (WebInspector.RenderingFrameTimelineView):
+        Increased column widths.
+
+        * UserInterface/Views/TimelineOverview.css:
+        (.timeline-overview > .graphs-container):
+        (body.mac-platform.legacy .timeline-overview > .graphs-container):
+        Updated for new ruler height.
+
+        * UserInterface/Views/TimelineOverview.js:
+        (WebInspector.TimelineOverview):
+        (WebInspector.TimelineOverview.prototype.get secondsPerPixel):
+        (WebInspector.TimelineOverview.prototype.set secondsPerPixel):
+        (WebInspector.TimelineOverview.prototype.get visibleDuration):
+        (WebInspector.TimelineOverview.prototype.set selectionDuration):
+        (WebInspector.TimelineOverview.prototype.updateLayout):
+        (WebInspector.TimelineOverview.prototype.get timelineRuler):
+        (WebInspector.TimelineOverview.prototype.canShowTimeline):
+        (WebInspector.TimelineOverview.prototype._handleScrollEvent):
+        (WebInspector.TimelineOverview.prototype._handleWheelEvent):
+        (WebInspector.TimelineOverview.prototype._timelineRemoved):
+        (WebInspector.TimelineOverview.prototype._timeRangeSelectionChanged):
+        (WebInspector.TimelineOverview.prototype.set currentTime): Deleted.
+        (WebInspector.TimelineOverview.prototype.updateLayoutIfNeeded): Deleted.
+        (WebInspector.TimelineOverview.prototype._needsLayout): Deleted.
+        Converted to base class. Derived classes provide settings and permitted timeline types.
+
+        * UserInterface/Views/TimelineRecordFrame.css:
+        (.timeline-record-frame):
+        (.timeline-record-frame > .frame):
+        (.timeline-record-frame > .frame > .duration):
+        (.timeline-record-frame > .frame > .duration.timeline-record-type-network):
+        (.timeline-record-frame > .frame > .duration.timeline-record-type-layout):
+        (.timeline-record-frame > .frame > .duration.timeline-record-type-script):
+        (.timeline-record-frame > .frame > .duration:last-child): Deleted.
+        New graph frames styles.
+
+        * UserInterface/Views/TimelineRecordFrame.js:
+        (WebInspector.TimelineRecordFrame):
+        (WebInspector.TimelineRecordFrame.prototype.get record):
+        (WebInspector.TimelineRecordFrame.prototype.set record):
+        (WebInspector.TimelineRecordFrame.prototype._updateChildElements.createDurationElement):
+        (WebInspector.TimelineRecordFrame.prototype.get element): Deleted.
+        Updated to use frame index ruler.
+        Removed dropped frames and frame combining logic.
+
+        * UserInterface/Views/TimelineRecordingContentView.js:
+        (WebInspector.TimelineRecordingContentView):
+        (WebInspector.TimelineRecordingContentView.prototype.shown):
+        (WebInspector.TimelineRecordingContentView.prototype.hidden):
+        (WebInspector.TimelineRecordingContentView.prototype.updateLayout):
+        (WebInspector.TimelineRecordingContentView.prototype._currentContentViewDidChange):
+        (WebInspector.TimelineRecordingContentView.prototype._updateTimes):
+        (WebInspector.TimelineRecordingContentView.prototype._updateTimelineOverviewHeight):
+        (WebInspector.TimelineRecordingContentView.prototype._getRenderingFrameTimeline):
+        (WebInspector.TimelineRecordingContentView.prototype._timelineRemoved):
+        (WebInspector.TimelineRecordingContentView.prototype._timelineCountChanged):
+        (WebInspector.TimelineRecordingContentView.prototype._recordingReset):
+        (WebInspector.TimelineRecordingContentView.prototype._timeRangeSelectionChanged):
+        (WebInspector.TimelineRecordingContentView.prototype.get currentTimelineView): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype.goForward): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype._contentViewSupplementalRepresentedObjectsDidChange): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype._update): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype._debuggerPaused): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype._debuggerResumed): Deleted.
+        (WebInspector.TimelineRecordingContentView.prototype._recordingTimesUpdated): Deleted.
+        Maintains two timeline overviews, switching between them based on the current content view.
+        Updated tree element filtering to support both overview rulers.
+
+        * UserInterface/Views/TimelineRuler.css:
+        (.timeline-ruler > .header):
+        (body.mac-platform.legacy .timeline-ruler > .header):
+        (.timeline-ruler > .header > .divider > .label):
+        (.timeline-ruler > .selection-drag):
+        (body.mac-platform.legacy .timeline-ruler > .selection-drag):
+        (.timeline-ruler > .selection-handle):
+        (body.mac-platform.legacy .timeline-ruler > .selection-handle):
+        (.timeline-ruler > .header > .divider): Deleted.
+        (.timeline-ruler > .selection-drag:active): Deleted.
+        Updated for new ruler height.
+
+        * UserInterface/Views/TimelineRuler.js:
+        (WebInspector.TimelineRuler):
+        (WebInspector.TimelineRuler.prototype.set formatLabelCallback):
+        (WebInspector.TimelineRuler.prototype.updateLayout):
+        (WebInspector.TimelineRuler.prototype._formatDividerLabelText):
+        (WebInspector.TimelineRuler.prototype.set allowsClippedLabels): Deleted.
+        (WebInspector.TimelineRuler.prototype._updateSelection): Deleted.
+        Added ability to customize label formatting.
+
+        * UserInterface/Views/TimelineSidebarPanel.css:
+        (.panel.timeline .navigation-bar.timelines-view):
+        (.sidebar > .panel.navigation.timeline > .title-bar):
+        (body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar):
+        (.sidebar > .panel.navigation.timeline > .title-bar.timelines):
+        (.sidebar > .panel.navigation.timeline > .navigation-bar-container):
+        (.sidebar > .panel.navigation.timeline > .navigation-bar-container > .navigation-bar):
+        (.sidebar > .panel.navigation.timeline > .title-bar.timeline-events):
+        (body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar.timeline-events):
+        (.sidebar > .panel.navigation.timeline > .timelines-content):
+        (.sidebar > .panel.navigation.timeline > .empty-content-placeholder):
+        (body.mac-platform.legacy .sidebar > .panel.navigation.timeline > :matches(.content, .empty-content-placeholder)):
+        (.sidebar > .panel.navigation.timeline > .timelines-content li.item.selected + li.item): Deleted.
+        (body.window-inactive .sidebar > .panel.navigation.timeline > .timelines-content li.item.selected + li.item): Deleted.
+        Updated for new navigation bar and ruler height.
+
+        * UserInterface/Views/TimelineSidebarPanel.js:
+        (WebInspector.TimelineSidebarPanel):
+        (WebInspector.TimelineSidebarPanel.prototype.get viewMode):
+        (WebInspector.TimelineSidebarPanel.prototype.canShowTimeline):
+        (WebInspector.TimelineSidebarPanel.showTimelineViewForTimeline.this._timelineTreeElementMap.get select):
+        (WebInspector.TimelineSidebarPanel.get this):
+        (WebInspector.TimelineSidebarPanel._timelineAdded.set this):
+        Added support for two view modes: Timelines and Rendering Frames.
+
+        * WebInspectorUI.vcxproj/WebInspectorUI.vcxproj:
+        * WebInspectorUI.vcxproj/WebInspectorUI.vcxproj.filters:
+        New files.
+
 2015-04-27  Timothy Hatcher  <timothy@apple.com>
 
         Web Inspector: Add new tab button to make it easy to bring a closed tab back
index c30cb23..190dc72 100644 (file)
@@ -50,19 +50,6 @@ WebInspector.TimelineManager = class TimelineManager extends WebInspector.Object
         setTimeout(delayedWork.bind(this), 0);
     }
 
-    // Static
-
-    static shouldShowViewForTimeline(timeline)
-    {
-        // COMPATIBILITY (iOS 8): TimelineAgent.EventType.RenderingFrame did not exist,
-        // fallback to displaying all other timelines.
-        if (window.TimelineAgent && !TimelineAgent.EventType.RenderingFrame)
-            return timeline.type !== WebInspector.TimelineRecord.Type.RenderingFrame;
-
-        // Don't show the Layout timeline view when the RenderingFrame timeline exists.
-        return timeline.type !== WebInspector.TimelineRecord.Type.Layout;
-    }
-
     // Public
 
     // The current recording that new timeline records will be appended to, if any.
index 17ef450..3474676 100644 (file)
     <script src="Views/ObjectTreeBaseTreeElement.js"></script>
     <script src="Views/SourceCodeTreeElement.js"></script>
     <script src="Views/StorageTreeElement.js"></script>
+    <script src="Views/TimelineOverview.js"></script>
     <script src="Views/TimelineRecordTreeElement.js"></script>
 
     <script src="Views/ConsoleTabContentView.js"></script>
     <script src="Views/LayoutTimelineDataGridNode.js"></script>
     <script src="Views/LayoutTimelineOverviewGraph.js"></script>
     <script src="Views/LayoutTimelineView.js"></script>
+    <script src="Views/LinearTimelineOverview.js"></script>
     <script src="Views/LogContentView.js"></script>
     <script src="Views/LogTreeElement.js"></script>
     <script src="Views/MetricsStyleDetailsPanel.js"></script>
     <script src="Views/RadioButtonNavigationItem.js"></script>
     <script src="Views/RenderingFrameDetailsSidebarPanel.js"></script>
     <script src="Views/RenderingFrameTimelineDataGridNode.js"></script>
+    <script src="Views/RenderingFrameTimelineOverview.js"></script>
     <script src="Views/RenderingFrameTimelineOverviewGraph.js"></script>
     <script src="Views/RenderingFrameTimelineView.js"></script>
     <script src="Views/ReplayDashboardView.js"></script>
     <script src="Views/SyntaxHighlightingSupport.js"></script>
     <script src="Views/TextContentView.js"></script>
     <script src="Views/TextResourceContentView.js"></script>
-    <script src="Views/TimelineOverview.js"></script>
     <script src="Views/TimelineRecordBar.js"></script>
     <script src="Views/TimelineRecordFrame.js"></script>
     <script src="Views/TimelineRecordingContentView.js"></script>
index ec57609..5e0c03c 100644 (file)
@@ -32,21 +32,26 @@ WebInspector.RenderingFrameTimelineRecord = class RenderingFrameTimelineRecord e
         this._children = children || [];
         this._durationByRecordType = new Map;
         this._durationRemainder = NaN;
-        this._frameNumber = WebInspector.RenderingFrameTimelineRecord._nextFrameNumber++;
+        this._frameIndex = WebInspector.RenderingFrameTimelineRecord._nextFrameIndex++;
     }
 
     // Static
 
-    static resetFrameNumber()
+    static resetFrameIndex()
     {
-        WebInspector.RenderingFrameTimelineRecord._nextFrameNumber = 1;
+        WebInspector.RenderingFrameTimelineRecord._nextFrameIndex = 0;
     }
 
     // Public
 
+    get frameIndex()
+    {
+        return this._frameIndex;
+    }
+
     get frameNumber()
     {
-        return this._frameNumber;
+        return this._frameIndex + 1;
     }
 
     get children()
@@ -98,4 +103,4 @@ WebInspector.RenderingFrameTimelineRecord = class RenderingFrameTimelineRecord e
 
 WebInspector.RenderingFrameTimelineRecord.TypeIdentifier = "rendering-frame-timeline-record";
 
-WebInspector.RenderingFrameTimelineRecord._nextFrameNumber = 1;
+WebInspector.RenderingFrameTimelineRecord._nextFrameIndex = 0;
index bf7171a..aa99b52 100644 (file)
@@ -109,7 +109,7 @@ WebInspector.TimelineRecording = class TimelineRecording extends WebInspector.Ob
         for (var timeline of this._timelines.values())
             timeline.reset(suppressEvents);
 
-        WebInspector.RenderingFrameTimelineRecord.resetFrameNumber();
+        WebInspector.RenderingFrameTimelineRecord.resetFrameIndex();
 
         if (!suppressEvents) {
             this.dispatchEventToListeners(WebInspector.TimelineRecording.Event.Reset);
diff --git a/Source/WebInspectorUI/UserInterface/Views/LinearTimelineOverview.js b/Source/WebInspectorUI/UserInterface/Views/LinearTimelineOverview.js
new file mode 100644 (file)
index 0000000..30087f9
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2015 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.LinearTimelineOverview = function(timelineRecording)
+{
+    // FIXME: Convert this to a WebInspector.TimelineOverview subclass, and call super().
+
+    var defaultSettingsValues = {
+        durationPerPixel: 0.01,
+        selectionStartValue: 0,
+        selectionDuration: 5
+    };
+
+    WebInspector.TimelineOverview.call(this, "linear", timelineRecording, 0.0001, 60, defaultSettingsValues);
+};
+
+WebInspector.LinearTimelineOverview.prototype = {
+    constructor: WebInspector.LinearTimelineOverview,
+    __proto__: WebInspector.TimelineOverview.prototype,
+
+    // Protected
+
+    canShowTimeline: function(timeline)
+    {
+        return timeline.type !== WebInspector.TimelineRecord.Type.RenderingFrame;
+    }
+};
index 580ff82..b957f1c 100644 (file)
@@ -50,8 +50,8 @@ WebInspector.RenderingFrameDetailsSidebarPanel = class RenderingFrameDetailsSide
         this.contentElement.appendChild(detailsSection.element);
 
         this._renderingFrameTimeline = null;
-        this._startTime = 0;
-        this._endTime = 0;
+        this._startFrameIndex = 0;
+        this._endFrameIndex = 0;
 
         this._emptyValuePlaceholderString = "\u2014";
 
@@ -70,13 +70,13 @@ WebInspector.RenderingFrameDetailsSidebarPanel = class RenderingFrameDetailsSide
         return !!this._renderingFrameTimeline;
     }
 
-    updateRangeSelection(startTime, endTime)
+    updateRangeSelection(startFrameIndex, endFrameIndex)
     {
-        if (this._startTime === startTime && this._endTime === endTime)
+        if (this._startFrameIndex === startFrameIndex && this._endFrameIndex === endFrameIndex)
             return;
 
-        this._startTime = startTime || 0;
-        this._endTime = endTime || 0;
+        this._startFrameIndex = startFrameIndex || 0;
+        this._endFrameIndex = endFrameIndex || 0;
 
         this.needsRefresh();
     }
@@ -173,12 +173,12 @@ WebInspector.RenderingFrameDetailsSidebarPanel = class RenderingFrameDetailsSide
         for (var record of this._renderingFrameTimeline.records) {
             console.assert(record instanceof WebInspector.RenderingFrameTimelineRecord);
             // If this frame is completely before the bounds of the graph, skip this record.
-            if (record.endTime < this._startTime)
+            if (record.frameIndex < Math.floor(this._startFrameIndex))
                 continue;
 
             // If this record is completely after the end time, break out now.
             // Records are sorted, so all records after this will be beyond the end time too.
-            if (record.startTime > this._endTime)
+            if (record.frameIndex > this._endFrameIndex)
                 break;
 
             records.push(record);
diff --git a/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverview.js b/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineOverview.js
new file mode 100644 (file)
index 0000000..30a7059
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2015 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.RenderingFrameTimelineOverview = function(timelineRecording)
+{
+    // FIXME: Convert this to a WebInspector.TimelineOverview subclass, and call super().
+
+    var minimumDurationPerPixel = 1 / WebInspector.TimelineRecordFrame.MaximumWidthPixels;
+    var maximumDurationPerPixel = 1 / WebInspector.TimelineRecordFrame.MinimumWidthPixels;
+    var defaultSettingsValues = {
+        durationPerPixel: minimumDurationPerPixel,
+        selectionStartValue: 0,
+        selectionDuration: 100
+    };
+
+    WebInspector.TimelineOverview.call(this, "frames", timelineRecording, minimumDurationPerPixel, maximumDurationPerPixel, defaultSettingsValues);
+
+    this.timelineRuler.formatLabelCallback = function(value) {
+        return value.toFixed(0);
+    };
+};
+
+WebInspector.RenderingFrameTimelineOverview.prototype = {
+    constructor: WebInspector.RenderingFrameTimelineOverview,
+    __proto__: WebInspector.TimelineOverview.prototype,
+
+    // Protected
+
+    canShowTimeline: function(timeline)
+    {
+        return timeline.type === WebInspector.TimelineRecord.Type.RenderingFrame;
+    }
+};
index 60c086d..d70ea1d 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+.timeline-overview > .graphs-container > .timeline-overview-graph.rendering-frame {
+    height: 100%;
+}
+
 .timeline-overview-graph.rendering-frame > .divider {
     position: absolute;
     z-index: 10;
index ff18145..0cc6294 100644 (file)
@@ -30,11 +30,11 @@ WebInspector.RenderingFrameTimelineOverviewGraph = function(timeline)
     this.element.classList.add(WebInspector.RenderingFrameTimelineOverviewGraph.StyleClassName);
 
     this._renderingFrameTimeline = timeline;
+    this._renderingFrameTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._timelineRecordAdded, this);
+
     this._timelineRecordFrames = [];
     this._graphHeightSeconds = NaN;
-    this._framesPerSecondDividers = new Map;
-
-    this._renderingFrameTimeline.addEventListener(WebInspector.Timeline.Event.RecordAdded, this._timelineRecordAdded, this);
+    this._framesPerSecondDividerMap = new Map;
 
     this.reset();
 };
@@ -70,7 +70,7 @@ WebInspector.RenderingFrameTimelineOverviewGraph.prototype = {
 
         this.element.removeChildren();
 
-        this._framesPerSecondDividers.clear();
+        this._framesPerSecondDividerMap.clear();
     },
 
     updateLayout()
@@ -80,28 +80,29 @@ WebInspector.RenderingFrameTimelineOverviewGraph.prototype = {
         if (!this._renderingFrameTimeline.records.length)
             return;
 
-        var secondsPerPixel = this.timelineOverview.secondsPerPixel;
+        var records = this._renderingFrameTimeline.records;
+        var startIndex = Math.floor(this.startTime);
+        var endIndex = Math.min(Math.floor(this.endTime), records.length - 1);
         var recordFrameIndex = 0;
 
-        function createFrame(records)
-        {
+        for (var i = startIndex; i <= endIndex; ++i) {
+            var record = records[i];
             var timelineRecordFrame = this._timelineRecordFrames[recordFrameIndex];
             if (!timelineRecordFrame)
-                timelineRecordFrame = this._timelineRecordFrames[recordFrameIndex] = new WebInspector.TimelineRecordFrame(this, records);
+                timelineRecordFrame = this._timelineRecordFrames[recordFrameIndex] = new WebInspector.TimelineRecordFrame(this, record);
             else
-                timelineRecordFrame.records = records;
+                timelineRecordFrame.record = record;
 
             timelineRecordFrame.refresh(this);
             if (!timelineRecordFrame.element.parentNode)
                 this.element.appendChild(timelineRecordFrame.element);
+
             ++recordFrameIndex;
         }
 
-        WebInspector.TimelineRecordFrame.createCombinedFrames(this._renderingFrameTimeline.records, secondsPerPixel, this, createFrame.bind(this));
-
         // Remove the remaining unused TimelineRecordFrames.
         for (; recordFrameIndex < this._timelineRecordFrames.length; ++recordFrameIndex) {
-            this._timelineRecordFrames[recordFrameIndex].records = null;
+            this._timelineRecordFrames[recordFrameIndex].record = null;
             this._timelineRecordFrames[recordFrameIndex].element.remove();
         }
 
@@ -131,7 +132,7 @@ WebInspector.RenderingFrameTimelineOverviewGraph.prototype = {
             if (dividerTop < 0.01 || dividerTop >= 1)
                 return;
 
-            var divider = this._framesPerSecondDividers.get(framesPerSecond);
+            var divider = this._framesPerSecondDividerMap.get(framesPerSecond);
             if (!divider) {
                 divider = document.createElement("div");
                 divider.classList.add("divider");
@@ -143,7 +144,7 @@ WebInspector.RenderingFrameTimelineOverviewGraph.prototype = {
 
                 this.element.appendChild(divider);
 
-                this._framesPerSecondDividers.set(framesPerSecond, divider);
+                this._framesPerSecondDividerMap.set(framesPerSecond, divider);
             }
 
             divider.style.marginTop = (dividerTop * overviewGraphHeight).toFixed(2) + "px";
index 5e52629..c4b43ca 100644 (file)
@@ -40,15 +40,15 @@ WebInspector.RenderingFrameTimelineView = function(timeline, extraArguments)
     columns.startTime.aligned = "right";
 
     columns.layoutTime.title = WebInspector.UIString("Layout");
-    columns.layoutTime.width = "10%";
+    columns.layoutTime.width = "15%";
     columns.layoutTime.aligned = "right";
 
     columns.scriptTime.title = WebInspector.UIString("Script");
-    columns.scriptTime.width = "10%";
+    columns.scriptTime.width = "15%";
     columns.scriptTime.aligned = "right";
 
     columns.otherTime.title = WebInspector.UIString("Other");
-    columns.otherTime.width = "10%";
+    columns.otherTime.width = "15%";
     columns.otherTime.aligned = "right";
 
     columns.totalTime.title = WebInspector.UIString("Total Time");
index 20da5cd..3dde678 100644 (file)
 
 .timeline-overview > .graphs-container {
     position: absolute;
-    top: 22px;
+    top: 29px;
     left: 0;
     bottom: 0;
     right: 0;
 }
 
+body.mac-platform.legacy .timeline-overview > .graphs-container {
+    top: 22px;
+}
+
 .timeline-overview > .graphs-container > .timeline-overview-graph {
     height: 36px;
 }
index 4506215..000da34 100644 (file)
@@ -23,7 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.TimelineOverview = function(timelineRecording)
+WebInspector.TimelineOverview = function(identifier, timelineRecording, minimumDurationPerPixel, maximumDurationPerPixel, defaultSettingsValues)
 {
     // FIXME: Convert this to a WebInspector.Object subclass, and call super().
     // WebInspector.Object.call(this);
@@ -60,18 +60,20 @@ WebInspector.TimelineOverview = function(timelineRecording)
     this._scrollWidthSizer.className = WebInspector.TimelineOverview.ScrollWidthSizerStyleClassName;
     this._scrollContainerElement.appendChild(this._scrollWidthSizer);
 
-    this._secondsPerPixelSetting = new WebInspector.Setting("timeline-overview-seconds-per-pixel", 0.01);
-    this._selectionStartTimeSetting = new WebInspector.Setting("timeline-overview-selection-start-time", 0);
-    this._selectionDurationSetting = new WebInspector.Setting("timeline-overview-selection-duration", 5);
+    this._durationPerPixelSetting = new WebInspector.Setting(identifier + "-timeline-overview-duration-per-pixel", defaultSettingsValues.durationPerPixel);
+    this._selectionStartValueSetting = new WebInspector.Setting(identifier + "-timeline-overview-selection-start-value", defaultSettingsValues.selectionStartValue);
+    this._selectionDurationSetting = new WebInspector.Setting(identifier + "-timeline-overview-selection-duration", defaultSettingsValues.selectionDuration);
 
     this._startTime = 0;
     this._currentTime = 0;
     this._endTime = 0;
-    this._secondsPerPixel = this._secondsPerPixelSetting.value;
+    this._minimumDurationPerPixel = minimumDurationPerPixel;
+    this._maximumDurationPerPixel = maximumDurationPerPixel;
+    this._durationPerPixel = Math.min(this._maximumDurationPerPixel, Math.max(this._minimumDurationPerPixel, this._durationPerPixelSetting.value));
     this._scrollStartTime = 0;
     this._cachedScrollContainerWidth = NaN;
 
-    this.selectionStartTime = this._selectionStartTimeSetting.value;
+    this.selectionStartTime = this._selectionStartValueSetting.value;
     this.selectionDuration = this._selectionDurationSetting.value;
 
     for (var timeline of this._recording.timelines.values())
@@ -82,7 +84,6 @@ WebInspector.TimelineOverview.StyleClassName = "timeline-overview";
 WebInspector.TimelineOverview.GraphsContainerStyleClassName = "graphs-container";
 WebInspector.TimelineOverview.ScrollContainerStyleClassName = "scroll-container";
 WebInspector.TimelineOverview.ScrollWidthSizerStyleClassName = "scroll-width-sizer";
-WebInspector.TimelineOverview.MinimumSecondsPerPixel = 0.001;
 WebInspector.TimelineOverview.ScrollDeltaDenominator = 500;
 
 WebInspector.TimelineOverview.Event = {
@@ -133,18 +134,18 @@ WebInspector.TimelineOverview.prototype = {
 
     get secondsPerPixel()
     {
-        return this._secondsPerPixel;
+        return this._durationPerPixel;
     },
 
     set secondsPerPixel(x)
     {
-        x = Math.max(WebInspector.TimelineOverview.MinimumSecondsPerPixel, x);
+        x = Math.min(this._maximumDurationPerPixel, Math.max(this._minimumDurationPerPixel, x));
 
-        if (this._secondsPerPixel === x)
+        if (this._durationPerPixel === x)
             return;
 
-        this._secondsPerPixel = x;
-        this._secondsPerPixelSetting.value = x;
+        this._durationPerPixel = x;
+        this._durationPerPixelSetting.value = x;
 
         this._needsLayout();
     },
@@ -186,7 +187,7 @@ WebInspector.TimelineOverview.prototype = {
             console.assert(this._cachedScrollContainerWidth > 0);
         }
 
-        return this._cachedScrollContainerWidth * this._secondsPerPixel;
+        return this._cachedScrollContainerWidth * this._durationPerPixel;
     },
 
     get selectionStartTime()
@@ -211,6 +212,7 @@ WebInspector.TimelineOverview.prototype = {
     set selectionDuration(x)
     {
         x = Math.max(WebInspector.TimelineRuler.MinimumSelectionTimeRange, x);
+
         this._timelineRuler.selectionEndTime = this._timelineRuler.selectionStartTime + x;
     },
 
@@ -268,7 +270,7 @@ WebInspector.TimelineOverview.prototype = {
 
         // 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);
+        var newWidth = Math.ceil(duration / this._durationPerPixel);
 
         // Update all relevant elements to the new required width.
         this._updateElementWidth(this._scrollWidthSizer, newWidth);
@@ -288,11 +290,11 @@ WebInspector.TimelineOverview.prototype = {
 
         this._timelineRuler.zeroTime = this._startTime;
         this._timelineRuler.startTime = scrollStartTime;
-        this._timelineRuler.secondsPerPixel = this._secondsPerPixel;
+        this._timelineRuler.secondsPerPixel = this._durationPerPixel;
 
         if (!this._dontUpdateScrollLeft) {
             this._ignoreNextScrollEvent = true;
-            this._scrollContainerElement.scrollLeft = Math.ceil((scrollStartTime - this._startTime) / this._secondsPerPixel);
+            this._scrollContainerElement.scrollLeft = Math.ceil((scrollStartTime - this._startTime) / this._durationPerPixel);
         }
 
         this._timelineRuler.updateLayout();
@@ -319,6 +321,19 @@ WebInspector.TimelineOverview.prototype = {
             timelineOverviewGraph.updateLayoutIfNeeded();
     },
 
+    // Protected
+
+    get timelineRuler()
+    {
+        return this._timelineRuler;
+    },
+
+    canShowTimeline: function(timeline)
+    {
+        // Implemented by subclasses.
+        console.error("Needs to be implemented by a subclass.");
+    },
+
     // Private
 
     _updateElementWidth: function(element, newWidth)
@@ -349,7 +364,7 @@ WebInspector.TimelineOverview.prototype = {
         this._dontUpdateScrollLeft = true;
 
         var scrollOffset = this._scrollContainerElement.scrollLeft;
-        this.scrollStartTime = this._startTime + (scrollOffset * this._secondsPerPixel);
+        this.scrollStartTime = this._startTime + (scrollOffset * this._durationPerPixel);
 
         // Force layout so we can update with the scroll position synchronously.
         this.updateLayoutIfNeeded();
@@ -376,13 +391,13 @@ WebInspector.TimelineOverview.prototype = {
 
         // Remember the mouse position in time.
         var mouseOffset = event.pageX - this._element.totalOffsetLeft;
-        var mousePositionTime = this._scrollStartTime + (mouseOffset * this._secondsPerPixel);
+        var mousePositionTime = this._scrollStartTime + (mouseOffset * this._durationPerPixel);
         var deviceDirection = event.webkitDirectionInvertedFromDevice ? 1 : -1;
 
-        this.secondsPerPixel += event.deltaY * (this._secondsPerPixel / WebInspector.TimelineOverview.ScrollDeltaDenominator) * deviceDirection;
+        this.secondsPerPixel += event.deltaY * (this._durationPerPixel / WebInspector.TimelineOverview.ScrollDeltaDenominator) * deviceDirection;
 
         // Center the zoom around the mouse based on the remembered mouse position time.
-        this.scrollStartTime = mousePositionTime - (mouseOffset * this._secondsPerPixel);
+        this.scrollStartTime = mousePositionTime - (mouseOffset * this._durationPerPixel);
 
         event.preventDefault();
         event.stopPropagation();
@@ -396,8 +411,7 @@ WebInspector.TimelineOverview.prototype = {
 
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
         console.assert(!this._timelineOverviewGraphsMap.has(timeline), timeline);
-
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
+        if (!this.canShowTimeline(timeline))
             return;
 
         var overviewGraph = new WebInspector.TimelineOverviewGraph(timeline);
@@ -410,7 +424,7 @@ WebInspector.TimelineOverview.prototype = {
     {
         var timeline = event.data.timeline;
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
+        if (!this.canShowTimeline(timeline))
             return;
 
         console.assert(this._timelineOverviewGraphsMap.has(timeline), timeline);
@@ -422,7 +436,7 @@ WebInspector.TimelineOverview.prototype = {
 
     _timeRangeSelectionChanged: function(event)
     {
-        this._selectionStartTimeSetting.value = this.selectionStartTime - this._startTime;
+        this._selectionStartValueSetting.value = this.selectionStartTime - this._startTime;
         this._selectionDurationSetting.value = this.selectionDuration;
 
         this.dispatchEventToListeners(WebInspector.TimelineOverview.Event.TimeRangeSelectionChanged);
index 7e5a4b1..aaad2a3 100644 (file)
@@ -25,8 +25,9 @@
 
 .timeline-record-frame {
     position: absolute;
-    height: 36px;
+    height: 108px;
     min-width: 4px;
+    width: 4px;
 
     overflow: hidden;
 
     z-index: 1;
     bottom: 1px;
     min-width: 4px;
+    width: 100%;
 
-    box-sizing: border-box;
-}
-
-.timeline-record-frame > .dropped {
-    position: absolute;
-    bottom: 1px;
-    right: 0;
+    padding-left: 1px;
 
-    min-width: 6px;
     box-sizing: border-box;
-
-    background: repeating-linear-gradient(-45deg, white, white 2px, rgb(234, 234, 234) 2px, rgb(234, 234, 234) 4px);
-
-    border-top-style: solid;
-    border-right-style: solid;
-    border-width: 1px;
-    border-color: rgb(221, 221, 221);
 }
 
 .timeline-record-frame > .frame > .duration {
 
     background-color: rgb(221, 221, 221);
 
-    border-color: rgb(176, 176, 176);
-    border-style: none solid solid solid;
-    border-width: 1px;
-}
-
-.timeline-record-frame > .frame > .duration:first-child {
-    border-top-style: solid;
+    border-bottom: solid 1px rgb(245, 245, 245);
 }
 
 .timeline-record-frame > .frame > .duration:last-child {
 }
 
 .timeline-record-frame > .frame > .duration.timeline-record-type-network {
-    background-color: rgb(120, 176, 225);
-    border-color: rgb(61, 147, 200);
+    background-color: rgb(61, 147, 200);
 }
 
 .timeline-record-frame > .frame > .duration.timeline-record-type-layout {
-    background-color: rgb(234, 153, 153);
-    border-color: rgb(212, 108, 108);
+    background-color: rgb(212, 108, 108);
 }
 
 .timeline-record-frame > .frame > .duration.timeline-record-type-script {
-    background-color: rgb(190, 148, 233);
-    border-color: rgb(153, 113, 185);
+    background-color: rgb(153, 113, 185);
 }
index 97848e5..1eea662 100644 (file)
@@ -23,7 +23,7 @@
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.TimelineRecordFrame = function(graphDataSource, records)
+WebInspector.TimelineRecordFrame = function(graphDataSource, record)
 {
     // FIXME: Convert this to a WebInspector.Object subclass, and call super().
     // WebInspector.Object.call(this);
@@ -32,88 +32,15 @@ WebInspector.TimelineRecordFrame = function(graphDataSource, records)
     this._element.classList.add(WebInspector.TimelineRecordFrame.StyleClassName);
 
     this._graphDataSource = graphDataSource;
-    this.records = records || [];
+    this._record = record || null;
 };
 
 // FIXME: Move to a WebInspector.Object subclass and we can remove this.
 WebInspector.Object.deprecatedAddConstructorFunctions(WebInspector.TimelineRecordFrame);
 
 WebInspector.TimelineRecordFrame.StyleClassName = "timeline-record-frame";
-WebInspector.TimelineRecordFrame.SixtyFpsFrameBudget = 0.0166;
-WebInspector.TimelineRecordFrame.MaximumCombinedWidthPixels = 12;
+WebInspector.TimelineRecordFrame.MaximumWidthPixels = 16;
 WebInspector.TimelineRecordFrame.MinimumWidthPixels = 4;
-WebInspector.TimelineRecordFrame.MinimumMarginPixels = 1;
-
-WebInspector.TimelineRecordFrame.createCombinedFrames = function(records, secondsPerPixel, graphDataSource, createFrameCallback)
-{
-    if (!records.length)
-        return;
-
-    var startTime = graphDataSource.startTime;
-    var currentTime = graphDataSource.currentTime;
-    var endTime = graphDataSource.endTime;
-
-    var visibleRecords = [];
-
-    for (var record of records) {
-        if (isNaN(record.startTime))
-            continue;
-
-        // If this frame 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;
-
-        visibleRecords.push(record);
-    }
-
-    if (!visibleRecords.length)
-        return;
-
-    var maximumCombinedFrameDuration = secondsPerPixel * WebInspector.TimelineRecordFrame.MaximumCombinedWidthPixels;
-    var minimumFrameDuration = secondsPerPixel * WebInspector.TimelineRecordFrame.MinimumWidthPixels;
-    var minimumMargin = secondsPerPixel * WebInspector.TimelineRecordFrame.MinimumMarginPixels;
-
-    var activeStartTime = NaN;
-    var activeEndTime = NaN;
-    var activeRecords = [];
-
-    function createFrameFromActiveRecords()
-    {
-        createFrameCallback(activeRecords);
-        activeRecords = [];
-        activeStartTime = NaN;
-        activeEndTime = NaN;
-    }
-
-    for (var record of visibleRecords) {
-        // Check if the previous record is far enough away to create the frame.
-        if (!isNaN(activeStartTime) && (activeStartTime + Math.max(activeEndTime - activeStartTime, minimumFrameDuration) + minimumMargin <= record.startTime))
-            createFrameFromActiveRecords();
-
-        // Check if active records exceeds the maximum combined frame width.
-        if (!isNaN(activeStartTime) && (activeEndTime - activeStartTime) > maximumCombinedFrameDuration)
-            createFrameFromActiveRecords();
-
-        // If this is a new frame, peg the start time.
-        if (isNaN(activeStartTime))
-            activeStartTime = record.startTime;
-
-        // Update the end time to be the maximum we encounter. endTime might be NaN, so "|| 0" to prevent Math.max from returning NaN.
-        if (!isNaN(record.endTime))
-            activeEndTime = Math.max(activeEndTime || 0, record.endTime);
-
-        activeRecords.push(record);
-    }
-
-    // Create the active frame for the last record if needed.
-    if (!isNaN(activeStartTime))
-        createFrameCallback(activeRecords);
-};
 
 WebInspector.TimelineRecordFrame.prototype = {
     constructor: WebInspector.TimelineRecordFrame,
@@ -126,62 +53,34 @@ WebInspector.TimelineRecordFrame.prototype = {
         return this._element;
     },
 
-    get duration()
+    get record()
     {
-        if (this.records.length === 0)
-            return 0;
-
-        return this.records.lastValue.endTime - this.records[0].startTime;
+        return this._record;
     },
 
-    get records()
+    set record(record)
     {
-        return this._records;
-    },
-
-    set records(records)
-    {
-        records = records || [];
-
-        if (!(records instanceof Array))
-            records = [records];
-
-        this._records = records;
+        this._record = record;
     },
 
     refresh(graphDataSource)
     {
-        if (!this.records || !this.records.length)
-            return false;
-
-        var firstRecord = this.records[0];
-        var frameStartTime = firstRecord.startTime;
-
-        // If this frame has no time info, return early.
-        if (isNaN(frameStartTime))
-            return false;
-
-        var graphStartTime = graphDataSource.startTime;
-        var graphEndTime = graphDataSource.endTime;
-        var graphCurrentTime = graphDataSource.currentTime;
-
-        // If this frame is completely after the current time, return early.
-        if (frameStartTime > graphCurrentTime)
+        if (!this._record)
             return false;
 
-        var frameEndTime = this.records.lastValue.endTime;
+        var frameIndex = this._record.frameIndex;
+        var graphStartFrameIndex = Math.floor(graphDataSource.startTime);
+        var graphEndFrameIndex = graphDataSource.endTime;
 
         // If this frame is completely before or after the bounds of the graph, return early.
-        if (frameEndTime < graphStartTime || frameStartTime > graphEndTime)
+        if (frameIndex < graphStartFrameIndex || frameIndex > graphEndFrameIndex)
             return false;
 
-        var graphDuration = graphEndTime - graphStartTime;
-        var recordLeftPosition = (frameStartTime - graphStartTime) / graphDuration;
-        this._updateElementPosition(this._element, recordLeftPosition, "left");
-
-        var recordWidth = (frameEndTime - frameStartTime) / graphDuration;
-        this._updateElementPosition(this._element, recordWidth, "width");
+        this._element.style.width = (1 / graphDataSource.timelineOverview.secondsPerPixel) + "px";
 
+        var graphDuration = graphDataSource.endTime - graphDataSource.startTime
+        var recordLeftPosition = (frameIndex - graphDataSource.startTime) / graphDuration;
+        this._updateElementPosition(this._element, recordLeftPosition, "left");
         this._updateChildElements(graphDataSource);
 
         return true;
@@ -193,72 +92,40 @@ WebInspector.TimelineRecordFrame.prototype = {
     {
         this._element.removeChildren();
 
-        console.assert(this.records.length);
-        if (!this.records.length)
+        console.assert(this._record);
+        if (!this._record)
             return;
 
         if (graphDataSource.graphHeightSeconds === 0)
             return;
 
-        // When combining multiple records into a frame, display the record with the longest duration rather than averaging.
-        var displayRecord = this.records.reduce(function(previousValue, currentValue) {
-            return currentValue.duration >= previousValue.duration ? currentValue : previousValue;
-        });
-
         var frameElement = document.createElement("div");
         frameElement.classList.add("frame");
         this._element.appendChild(frameElement);
 
-        var frameHeight = displayRecord.duration / graphDataSource.graphHeightSeconds;
+        var frameHeight = this._record.duration / graphDataSource.graphHeightSeconds;
         this._updateElementPosition(frameElement, frameHeight, "height");
 
         function createDurationElement(duration, recordType)
         {
             var element = document.createElement("div");
-            this._updateElementPosition(element, duration / displayRecord.duration, "height");
+            this._updateElementPosition(element, duration / this._record.duration, "height");
             element.classList.add("duration");
             if (recordType)
                 element.classList.add(recordType);
             return element;
         }
 
-        if (displayRecord.durationRemainder > 0)
-            frameElement.appendChild(createDurationElement.call(this, displayRecord.durationRemainder));
+        if (this._record.durationRemainder > 0)
+            frameElement.appendChild(createDurationElement.call(this, this._record.durationRemainder));
 
         for (var type in WebInspector.TimelineRecord.Type) {
             var recordType = WebInspector.TimelineRecord.Type[type];
-            var duration = displayRecord.durationForRecords(recordType);
+            var duration = this._record.durationForRecords(recordType);
             if (duration === 0)
                 continue;
             frameElement.appendChild(createDurationElement.call(this, duration, recordType));
         }
-
-        // Add "includes-dropped" style class if multiple records are being combined in the frame,
-        // and one of those records exceeds the 60 fps frame budget.
-        if (this.records.length > 1 && displayRecord.duration > WebInspector.TimelineRecordFrame.SixtyFpsFrameBudget)
-            frameElement.classList.add("includes-dropped");
-
-        // If the display record is the last combined record and also exceeds the 60 fps budget,
-        // add a "dropped" element to the right of the frame.
-        var frameWidth = 1;
-        var secondsPerPixel = this._graphDataSource.timelineOverview.secondsPerPixel;
-        var minimumRecordDuration = secondsPerPixel * WebInspector.TimelineRecordFrame.MinimumWidthPixels * 2;    // Combine minimum widths of the frame element and dropped element.
-
-        if (displayRecord === this.records.lastValue && displayRecord.duration > WebInspector.TimelineRecordFrame.SixtyFpsFrameBudget && displayRecord.duration >= minimumRecordDuration) {
-            var overflowDuration = displayRecord.duration - WebInspector.TimelineRecordFrame.SixtyFpsFrameBudget;
-            var droppedElementWidth = overflowDuration / displayRecord.duration;
-            frameWidth -= droppedElementWidth;
-
-            var droppedElement = document.createElement("div");
-            droppedElement.className = "dropped";
-
-            this._element.appendChild(droppedElement);
-
-            this._updateElementPosition(droppedElement, frameHeight, "height");
-            this._updateElementPosition(droppedElement, droppedElementWidth, "width");
-        }
-
-        this._updateElementPosition(frameElement, frameWidth, "width");
     },
 
     _updateElementPosition(element, newPosition, property)
index e523be9..4a779fe 100644 (file)
@@ -36,9 +36,14 @@ WebInspector.TimelineRecordingContentView = function(recording, extraArguments)
 
     this.element.classList.add(WebInspector.TimelineRecordingContentView.StyleClassName);
 
-    this._timelineOverview = new WebInspector.TimelineOverview(this._recording);
-    this._timelineOverview.addEventListener(WebInspector.TimelineOverview.Event.TimeRangeSelectionChanged, this._timeRangeSelectionChanged, this);
-    this.element.appendChild(this._timelineOverview.element);
+    this._linearTimelineOverview = new WebInspector.LinearTimelineOverview(this._recording);
+    this._linearTimelineOverview.addEventListener(WebInspector.TimelineOverview.Event.TimeRangeSelectionChanged, this._timeRangeSelectionChanged, this);
+
+    this._renderingFrameTimelineOverview = new WebInspector.RenderingFrameTimelineOverview(this._recording);
+    this._renderingFrameTimelineOverview.addEventListener(WebInspector.TimelineOverview.Event.TimeRangeSelectionChanged, this._timeRangeSelectionChanged, this);
+
+    this._currentTimelineOverview = this._linearTimelineOverview;
+    this.element.appendChild(this._currentTimelineOverview.element);
 
     this._contentViewContainer = new WebInspector.ContentViewContainer();
     this._contentViewContainer.addEventListener(WebInspector.ContentViewContainer.Event.CurrentContentViewDidChange, this._currentContentViewDidChange, this);
@@ -54,7 +59,7 @@ WebInspector.TimelineRecordingContentView = function(recording, extraArguments)
     this._clearTimelineNavigationItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._clearTimeline, this);
 
     this._overviewTimelineView = new WebInspector.OverviewTimelineView(recording, {timelineSidebarPanel: this._timelineSidebarPanel});
-    this._overviewTimelineView.secondsPerPixel = this._timelineOverview.secondsPerPixel;
+    this._overviewTimelineView.secondsPerPixel = this._linearTimelineOverview.secondsPerPixel;
 
     this._timelineViewMap = new Map;
     this._pathComponentMap = new Map;
@@ -166,7 +171,7 @@ WebInspector.TimelineRecordingContentView.prototype = {
 
     shown: function()
     {
-        this._timelineOverview.shown();
+        this._currentTimelineOverview.shown();
         this._contentViewContainer.shown();
         this._clearTimelineNavigationItem.enabled = this._recording.isWritable();
 
@@ -176,7 +181,7 @@ WebInspector.TimelineRecordingContentView.prototype = {
 
     hidden: function()
     {
-        this._timelineOverview.hidden();
+        this._currentTimelineOverview.hidden();
         this._contentViewContainer.hidden();
 
         if (this._updating)
@@ -216,7 +221,7 @@ WebInspector.TimelineRecordingContentView.prototype = {
 
     updateLayout: function()
     {
-        this._timelineOverview.updateLayoutForResize();
+        this._currentTimelineOverview.updateLayoutForResize();
 
         var currentContentView = this._contentViewContainer.currentContentView;
         if (currentContentView)
@@ -237,7 +242,6 @@ WebInspector.TimelineRecordingContentView.prototype = {
     restoreFromCookie: function(cookie)
     {
         var timelineType = cookie[WebInspector.TimelineRecordingContentView.SelectedTimelineTypeCookieKey];
-
         if (timelineType === WebInspector.TimelineRecordingContentView.OverviewTimelineViewCookieValue)
             this.showOverviewTimelineView();
         else
@@ -257,10 +261,27 @@ WebInspector.TimelineRecordingContentView.prototype = {
         if (this.currentTimelineView && !this.currentTimelineView.matchTreeElementAgainstCustomFilters(treeElement))
             return false;
 
-        var startTime = this._timelineOverview.selectionStartTime;
-        var endTime = this._timelineOverview.selectionStartTime + this._timelineOverview.selectionDuration;
+        var startTime = this._currentTimelineOverview.selectionStartTime;
+        var endTime = startTime + this._currentTimelineOverview.selectionDuration;
         var currentTime = this._currentTime || this._recording.startTime;
 
+        if (this._timelineSidebarPanel.viewMode === WebInspector.TimelineSidebarPanel.ViewMode.RenderingFrames) {
+            var timeline = this._getRenderingFrameTimeline();
+            console.assert(timeline);
+
+            if (timeline && timeline.records.length) {
+                var startIndex = Math.floor(startTime);
+                if (startIndex >= timeline.records.length)
+                    return false;
+
+                var endIndex = Math.min(Math.floor(endTime), timeline.records.length - 1);
+                console.assert(startIndex <= endIndex, startIndex);
+
+                startTime = timeline.records[startIndex].startTime;
+                endTime = timeline.records[endIndex].endTime;
+            }
+        }
+
         function checkTimeBounds(itemStartTime, itemEndTime)
         {
             itemStartTime = itemStartTime || currentTime;
@@ -312,16 +333,32 @@ WebInspector.TimelineRecordingContentView.prototype = {
 
     _currentContentViewDidChange: function(event)
     {
+        var newTimelineOverview = this._linearTimelineOverview;
         var timelineView = this.currentTimelineView;
         if (timelineView) {
             this._timelineSidebarPanel.contentTreeOutline = timelineView.navigationSidebarTreeOutline;
             this._timelineSidebarPanel.contentTreeOutlineLabel = timelineView.navigationSidebarTreeOutlineLabel;
 
-            timelineView.startTime = this._timelineOverview.selectionStartTime;
-            timelineView.endTime = this._timelineOverview.selectionStartTime + this._timelineOverview.selectionDuration;
+            if (timelineView.representedObject.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+                newTimelineOverview = this._renderingFrameTimelineOverview;
+
+            timelineView.startTime = newTimelineOverview.selectionStartTime;
+            timelineView.endTime = newTimelineOverview.selectionStartTime + newTimelineOverview.selectionDuration;
             timelineView.currentTime = this._currentTime;
         }
 
+        if (newTimelineOverview !== this._currentTimelineOverview) {
+            this._currentTimelineOverview.hidden();
+
+            this.element.insertBefore(newTimelineOverview.element, this._currentTimelineOverview.element);
+            this.element.removeChild(this._currentTimelineOverview.element);
+
+            this._currentTimelineOverview = newTimelineOverview;
+            this._currentTimelineOverview.shown();
+
+            this._updateTimelineOverviewHeight();
+        }
+
         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
         this.dispatchEventToListeners(WebInspector.ContentView.Event.NavigationItemsDidChange);
     },
@@ -375,10 +412,10 @@ WebInspector.TimelineRecordingContentView.prototype = {
     _updateTimes: function(startTime, currentTime, endTime)
     {
         if (this._startTimeNeedsReset && !isNaN(startTime)) {
-            var selectionOffset = this._timelineOverview.selectionStartTime - this._timelineOverview.startTime;
+            var selectionOffset = this._linearTimelineOverview.selectionStartTime - this._linearTimelineOverview.startTime;
 
-            this._timelineOverview.startTime = startTime;
-            this._timelineOverview.selectionStartTime = startTime + selectionOffset;
+            this._linearTimelineOverview.startTime = startTime;
+            this._linearTimelineOverview.selectionStartTime = startTime + selectionOffset;
 
             this._overviewTimelineView.zeroTime = startTime;
             for (var timelineView of this._timelineViewMap.values())
@@ -387,17 +424,21 @@ WebInspector.TimelineRecordingContentView.prototype = {
             delete this._startTimeNeedsReset;
         }
 
-        this._timelineOverview.endTime = Math.max(endTime, currentTime);
+        this._linearTimelineOverview.endTime = Math.max(endTime, currentTime);
 
         this._currentTime = currentTime;
-        this._timelineOverview.currentTime = currentTime;
+        this._linearTimelineOverview.currentTime = currentTime;
         if (this.currentTimelineView)
             this.currentTimelineView.currentTime = currentTime;
 
+        var timeline = this._getRenderingFrameTimeline();
+        if (timeline)
+            this._renderingFrameTimelineOverview.endTime = timeline.records.length;
+
         this._timelineSidebarPanel.updateFilter();
 
         // Force a layout now since we are already in an animation frame and don't need to delay it until the next.
-        this._timelineOverview.updateLayoutIfNeeded();
+        this._currentTimelineOverview.updateLayoutIfNeeded();
         if (this.currentTimelineView)
             this.currentTimelineView.updateLayoutIfNeeded();
     },
@@ -489,6 +530,39 @@ WebInspector.TimelineRecordingContentView.prototype = {
         this._recording.reset();
     },
 
+    _updateTimelineOverviewHeight: function()
+    {
+        const timelineHeight = 36;
+        const renderingFramesTimelineHeight = 108;
+        const rulerHeight = 29;
+
+        var overviewHeight;
+
+        if (this.currentTimelineView && this.currentTimelineView.representedObject.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+            overviewHeight = renderingFramesTimelineHeight;
+        else {
+            var timelineCount = this._timelineViewMap.size;
+            if (this._getRenderingFrameTimeline())
+                timelineCount--;
+
+            overviewHeight = timelineCount * timelineHeight;
+        }
+
+        var styleValue = (rulerHeight + overviewHeight) + "px";
+        this._currentTimelineOverview.element.style.height = styleValue;
+        this._contentViewContainer.element.style.top = styleValue;
+    },
+
+    _getRenderingFrameTimeline: function()
+    {
+        for (var timeline of this._timelineViewMap.keys()) {
+            if (timeline.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+                return timeline;
+        }
+
+        return null;
+    },
+
     _timelineAdded: function(timelineOrEvent)
     {
         var timeline = timelineOrEvent;
@@ -496,9 +570,6 @@ WebInspector.TimelineRecordingContentView.prototype = {
             timeline = timelineOrEvent.data.timeline;
 
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
-            return;
-
         console.assert(!this._timelineViewMap.has(timeline), timeline);
 
         this._timelineViewMap.set(timeline, new WebInspector.ContentView(timeline, {timelineSidebarPanel: this._timelineSidebarPanel}));
@@ -514,9 +585,6 @@ WebInspector.TimelineRecordingContentView.prototype = {
     {
         var timeline = event.data.timeline;
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
-            return;
-
         console.assert(this._timelineViewMap.has(timeline), timeline);
 
         var timelineView = this._timelineViewMap.take(timeline);
@@ -540,11 +608,7 @@ WebInspector.TimelineRecordingContentView.prototype = {
             previousPathComponent = pathComponent;
         }
 
-        var timelineCount = this._timelineViewMap.size;
-        const timelineHeight = 36;
-        const extraOffset = 22;
-        this._timelineOverview.element.style.height = (timelineCount * timelineHeight + extraOffset) + "px";
-        this._contentViewContainer.element.style.top = (timelineCount * timelineHeight + extraOffset) + "px";
+        this._updateTimelineOverviewHeight();
     },
 
     _recordingReset: function(event)
@@ -563,7 +627,8 @@ WebInspector.TimelineRecordingContentView.prototype = {
         this._recording.removeEventListener(WebInspector.TimelineRecording.Event.TimesUpdated, this._recordingTimesUpdated, this);
         this._waitingToResetCurrentTime = false;
 
-        this._timelineOverview.reset();
+        this._linearTimelineOverview.reset();
+        this._renderingFrameTimelineOverview.reset();
         this._overviewTimelineView.reset();
         for (var timelineView of this._timelineViewMap.values())
             timelineView.reset();
@@ -580,10 +645,11 @@ WebInspector.TimelineRecordingContentView.prototype = {
     _timeRangeSelectionChanged: function(event)
     {
         if (this.currentTimelineView) {
-            this.currentTimelineView.startTime = this._timelineOverview.selectionStartTime;
-            this.currentTimelineView.endTime = this._timelineOverview.selectionStartTime + this._timelineOverview.selectionDuration;
+            this.currentTimelineView.startTime = this._currentTimelineOverview.selectionStartTime;
+            this.currentTimelineView.endTime = this._currentTimelineOverview.selectionStartTime + this._currentTimelineOverview.selectionDuration;
 
-            WebInspector.renderingFrameDetailsSidebarPanel.updateRangeSelection(this.currentTimelineView.startTime, this.currentTimelineView.endTime);
+            if (this.currentTimelineView.representedObject.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+                WebInspector.renderingFrameDetailsSidebarPanel.updateRangeSelection(this.currentTimelineView.startTime, this.currentTimelineView.endTime);
         }
 
         // Delay until the next frame to stay in sync with the current timeline view's time-based layout changes.
index 2d86793..5ad0646 100644 (file)
     top: 0;
     left: 0;
     right: 0;
+    height: 29px;
+}
+
+body.mac-platform.legacy .timeline-ruler > .header {
     height: 22px;
 }
 
@@ -58,7 +62,7 @@
 
 .timeline-ruler > .header > .divider > .label {
     position: absolute;
-    top: 5px;
+    top: 8px;
     right: 5px;
     font-size: 9px;
     color: rgb(128, 128, 128);
 .timeline-ruler > .selection-drag {
     position: absolute;
     top: 0;
-    height: 22px;
+    height: 29px;
     cursor: -webkit-grab;
     pointer-events: all;
 }
 
+body.mac-platform.legacy .timeline-ruler > .selection-drag {
+    height: 22px;
+}
+
 .timeline-ruler > .selection-drag:active {
     cursor: -webkit-grabbing;
 }
     position: absolute;
     top: 0;
     width: 8px;
-    height: 21px;
+    height: 28px;
     border-radius: 5px;
     background-color: rgb(164, 164, 164);
     border: 1px solid white;
     z-index: 15;
 }
 
+body.mac-platform.legacy .timeline-ruler > .selection-handle {
+    height: 21px;
+}
+
 .timeline-ruler > .selection-handle.left {
     -webkit-transform: translateX(-4px);
 }
index d4c2314..e61fbf0 100644 (file)
@@ -49,6 +49,7 @@ WebInspector.TimelineRuler = function()
     this._endTimePinned = false;
     this._allowsClippedLabels = false;
     this._allowsTimeRangeSelection = false;
+    this._formatLabelCallback = null;
 
     this._markerElementMap = new Map;
 };
@@ -100,6 +101,18 @@ WebInspector.TimelineRuler.prototype = {
         this._needsLayout();
     },
 
+    set formatLabelCallback(x)
+    {
+        console.assert(typeof x === "function" || !x, x);
+
+        if (this._formatLabelCallback === x)
+            return;
+
+        this._formatLabelCallback = x || null;
+
+        this._needsLayout();
+    },
+
     get allowsTimeRangeSelection()
     {
         return this._allowsTimeRangeSelection;
@@ -403,7 +416,7 @@ WebInspector.TimelineRuler.prototype = {
 
             console.assert(dividerElement.firstChild.classList.contains(WebInspector.TimelineRuler.DividerLabelElementStyleClassName));
 
-            dividerElement.firstChild.textContent = isNaN(dividerTime) ? "" : Number.secondsToString(dividerTime - this._zeroTime, true);
+            dividerElement.firstChild.textContent = isNaN(dividerTime) ? "" : this._formatDividerLabelText(dividerTime - this._zeroTime);
             dividerElement = dividerElement.nextSibling;
         }
 
@@ -592,6 +605,14 @@ WebInspector.TimelineRuler.prototype = {
             this._dispatchTimeRangeSelectionChangedEvent();
     },
 
+    _formatDividerLabelText: function(value)
+    {
+        if (this._formatLabelCallback)
+            return this._formatLabelCallback(value);
+
+        return Number.secondsToString(value, true);
+    },
+
     _dispatchTimeRangeSelectionChangedEvent: function()
     {
         delete this._timeRangeSelectionChanged;
index 625a3d6..bc51c9f 100644 (file)
@@ -116,12 +116,16 @@ body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .status-bar > .
     top: 0;
 }
 
+.panel.timeline .navigation-bar.timelines-view {
+    justify-content: flex-end;
+}
+
 .sidebar > .panel.navigation.timeline > .title-bar {
     position: absolute;
     left: 0;
     right: 0;
 
-    height: 22px;
+    height: 29px;
 
     border-bottom: 1px solid rgb(179, 179, 179);
     background-color: rgb(242, 242, 242);
@@ -140,6 +144,8 @@ body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .status-bar > .
 }
 
 body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar {
+    height: 22px;
+
     background-color: transparent;
     background-image: linear-gradient(to bottom, rgb(238, 240, 244), rgb(224, 226, 230));
     text-shadow: rgba(255, 255, 255, 0.5) 0 1px 0;
@@ -147,6 +153,22 @@ body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar {
 
 .sidebar > .panel.navigation.timeline > .title-bar.timelines {
     top: 29px;
+    padding: 8px 9px;
+}
+
+.sidebar > .panel.navigation.timeline > .navigation-bar-container {
+    position: absolute;
+    top: 29px;
+    left: 0;
+    right: 0;
+}
+
+.sidebar > .panel.navigation.timeline > .navigation-bar-container > .navigation-bar {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    align-content: center;
 }
 
 body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar.timelines {
@@ -156,16 +178,16 @@ body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar.time
 .sidebar > .panel.navigation.timeline > .title-bar.timeline-events {
     height: 23px;
     border-top: 1px solid rgb(179, 179, 179);
-    top: 159px;
+    top: 166px;
 }
 
 body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .title-bar.timeline-events {
-    top: 152px;
+    top: 159px;
 }
 
 .sidebar > .panel.navigation.timeline > .timelines-content {
     position: absolute;
-    top: 51px;
+    top: 58px;
     height: 108px;
     left: 0;
     right: 0;
@@ -232,11 +254,11 @@ body.mac-platform.legacy .sidebar > .panel.navigation.timeline > .timelines-cont
 
 .sidebar > .panel.navigation.timeline > .content,
 .sidebar > .panel.navigation.timeline > .empty-content-placeholder {
-    top: 182px;
+    top: 189px;
 }
 
 body.mac-platform.legacy .sidebar > .panel.navigation.timeline > :matches(.content, .empty-content-placeholder) {
-    top: 175px;
+    top: 182px;
 }
 
 .sidebar > .panel.navigation.timeline.timeline-recording-content-view-showing > .content {
index c2386ba..b4c20e8 100644 (file)
@@ -34,6 +34,7 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         this._timelineEventsTitleBarElement = document.createElement("div");
         this._timelineEventsTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TitleBarStyleClass);
         this._timelineEventsTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TimelineEventsTitleBarStyleClass);
+
         this.element.insertBefore(this._timelineEventsTitleBarElement, this.element.firstChild);
 
         this.contentTreeOutlineLabel = "";
@@ -44,6 +45,8 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
 
         this._displayedRecording = null;
         this._displayedContentView = null;
+        this._viewMode = null;
+        this._previousTimelineSelection = null;
 
         // Maintain an invisible tree outline containing tree elements for all recordings.
         // The visible recording's tree element is selected when the content view changes.
@@ -62,11 +65,26 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
 
         this._timelineTreeElementMap = new Map;
 
-        var timelinesTitleBarElement = document.createElement("div");
-        timelinesTitleBarElement.textContent = WebInspector.UIString("Timelines");
-        timelinesTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TitleBarStyleClass);
-        timelinesTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TimelinesTitleBarStyleClass);
-        this.element.insertBefore(timelinesTitleBarElement, this.element.firstChild);
+        // COMPATIBILITY (iOS 8): TimelineAgent.EventType.RenderingFrame did not exist.
+        this._renderingFramesSupported = window.TimelineAgent && TimelineAgent.EventType.RenderingFrame;
+
+        if (this._renderingFramesSupported) {
+            var timelinesNavigationItem = new WebInspector.RadioButtonNavigationItem(WebInspector.TimelineSidebarPanel.ViewMode.Timelines, WebInspector.UIString("Timelines"))
+            var renderingFramesNavigationItem = new WebInspector.RadioButtonNavigationItem(WebInspector.TimelineSidebarPanel.ViewMode.RenderingFrames, WebInspector.UIString("Rendering Frames"))
+            this._viewModeNavigationBar = new WebInspector.NavigationBar(null, [timelinesNavigationItem, renderingFramesNavigationItem], "tablist");
+            this._viewModeNavigationBar.addEventListener(WebInspector.NavigationBar.Event.NavigationItemSelected, this._viewModeSelected, this);
+
+            var container = document.createElement("div");
+            container.className = "navigation-bar-container";
+            container.appendChild(this._viewModeNavigationBar.element);
+            this.element.insertBefore(container, this.element.firstChild);
+        } else {
+            var timelinesTitleBarElement = document.createElement("div");
+            timelinesTitleBarElement.textContent = WebInspector.UIString("Timelines");
+            timelinesTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TitleBarStyleClass);
+            timelinesTitleBarElement.classList.add(WebInspector.TimelineSidebarPanel.TimelinesTitleBarStyleClass);
+            this.element.insertBefore(timelinesTitleBarElement, this.element.firstChild);
+        }
 
         var statusBarElement = this._statusBarElement = document.createElement("div");
         statusBarElement.classList.add(WebInspector.TimelineSidebarPanel.StatusBarStyleClass);
@@ -85,16 +103,16 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
 
         WebInspector.showReplayInterfaceSetting.addEventListener(WebInspector.Setting.Event.Changed, this._updateReplayInterfaceVisibility, this);
 
-        // We always create a navigation bar; its visibility is controlled by WebInspector.showReplayInterfaceSetting.
-        this._navigationBar = new WebInspector.NavigationBar;
-        this.element.appendChild(this._navigationBar.element);
+        // We always create a replay navigation bar; its visibility is controlled by WebInspector.showReplayInterfaceSetting.
+        this._replayNavigationBar = new WebInspector.NavigationBar;
+        this.element.appendChild(this._replayNavigationBar.element);
 
         var toolTip = WebInspector.UIString("Begin Capturing");
         var altToolTip = WebInspector.UIString("End Capturing");
         this._replayCaptureButtonItem = new WebInspector.ActivateButtonNavigationItem("replay-capture", toolTip, altToolTip, "Images/Circle.svg", 16, 16);
         this._replayCaptureButtonItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._replayCaptureButtonClicked, this);
         this._replayCaptureButtonItem.enabled = true;
-        this._navigationBar.addNavigationItem(this._replayCaptureButtonItem);
+        this._replayNavigationBar.addNavigationItem(this._replayCaptureButtonItem);
 
         var pauseImage, resumeImage;
         if (WebInspector.Platform.isLegacyMacOS) {
@@ -110,13 +128,13 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         this._replayPauseResumeButtonItem = new WebInspector.ToggleButtonNavigationItem("replay-pause-resume", toolTip, altToolTip, resumeImage.src, pauseImage.src, pauseImage.width, pauseImage.height, true);
         this._replayPauseResumeButtonItem.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._replayPauseResumeButtonClicked, this);
         this._replayPauseResumeButtonItem.enabled = false;
-        this._navigationBar.addNavigationItem(this._replayPauseResumeButtonItem);
+        this._replayNavigationBar.addNavigationItem(this._replayPauseResumeButtonItem);
 
         WebInspector.replayManager.addEventListener(WebInspector.ReplayManager.Event.CaptureStarted, this._captureStarted, this);
         WebInspector.replayManager.addEventListener(WebInspector.ReplayManager.Event.CaptureStopped, this._captureStopped, this);
 
         this._statusBarElement.oncontextmenu = this._contextMenuNavigationBarOrStatusBar.bind(this);
-        this._navigationBar.element.oncontextmenu = this._contextMenuNavigationBarOrStatusBar.bind(this);
+        this._replayNavigationBar.element.oncontextmenu = this._contextMenuNavigationBarOrStatusBar.bind(this);
         this._updateReplayInterfaceVisibility();
 
         WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.RecordingCreated, this._recordingCreated, this);
@@ -137,6 +155,11 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
             this.contentBrowser.showContentView(this._displayedContentView);
     }
 
+    get viewMode()
+    {
+        return this._viewMode;
+    }
+
     showDefaultContentView()
     {
         if (this._displayedContentView)
@@ -239,17 +262,28 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
 
         this._displayedContentView.showOverviewTimelineView();
         this.contentBrowser.showContentView(this._displayedContentView);
+
+        var selectedByUser = false;
+        this._changeViewMode(this._viewModeForTimeline(null), selectedByUser);
     }
 
     showTimelineViewForTimeline(timeline)
     {
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        console.assert(this._timelineTreeElementMap.has(timeline), "Cannot show timeline because it does not belong to the shown recording.", timeline);
+        console.assert(this._displayedRecording.timelines.has(timeline.type), "Cannot show timeline because it does not belong to the shown recording.", timeline.type);
+
+        if (this._timelineTreeElementMap.has(timeline)) {
+            // Defer showing the relevant timeline to the onselect handler of the timelines tree element.
+            var wasSelectedByUser = true;
+            var shouldSuppressOnSelect = false;
+            this._timelineTreeElementMap.get(timeline).select(true, wasSelectedByUser, shouldSuppressOnSelect, true);
+        } else {
+            this._displayedContentView.showTimelineViewForTimeline(timeline);
+            this.contentBrowser.showContentView(this._displayedContentView);
+        }
 
-        // Defer showing the relevant timeline to the onselect handler of the timelines tree element.
-        var wasSelectedByUser = true;
-        var shouldSuppressOnSelect = false;
-        this._timelineTreeElementMap.get(timeline).select(true, wasSelectedByUser, shouldSuppressOnSelect, true);
+        var selectedByUser = false;
+        this._changeViewMode(this._viewModeForTimeline(timeline), selectedByUser);
     }
 
     // Protected
@@ -288,11 +322,15 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
 
         cookie[WebInspector.TimelineSidebarPanel.ShowingTimelineRecordingContentViewCookieKey] = this.contentBrowser.currentContentView instanceof WebInspector.TimelineRecordingContentView;
 
-        var selectedTreeElement = this._timelinesTreeOutline.selectedTreeElement;
-        if (selectedTreeElement)
-            cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = selectedTreeElement.representedObject.type;
-        else
-            cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue;
+        if (this._viewMode === WebInspector.TimelineSidebarPanel.ViewMode.RenderingFrames)
+            cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineRecord.Type.RenderingFrame;
+        else {
+            var selectedTreeElement = this._timelinesTreeOutline.selectedTreeElement;
+            if (selectedTreeElement)
+                cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = selectedTreeElement.representedObject.type;
+            else
+                cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue;    
+        }
 
         super.saveStateToCookie(cookie);
     }
@@ -311,9 +349,10 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         this._restoredShowingTimelineRecordingContentView = cookie[WebInspector.TimelineSidebarPanel.ShowingTimelineRecordingContentViewCookieKey];
 
         var selectedTimelineViewIdentifier = cookie[WebInspector.TimelineSidebarPanel.SelectedTimelineViewIdentifierCookieKey];
-        if (!selectedTimelineViewIdentifier || selectedTimelineViewIdentifier === WebInspector.TimelineSidebarPanel.OverviewTimelineIdentifierCookieValue)
-            this.showTimelineOverview();
-        else if (this._displayedRecording.timelines.has(selectedTimelineViewIdentifier))
+        if (selectedTimelineViewIdentifier === WebInspector.TimelineRecord.Type.RenderingFrame && !this._renderingFramesSupported)
+            selectedTimelineViewIdentifier = null;
+
+        if (selectedTimelineViewIdentifier && this._displayedRecording.timelines.has(selectedTimelineViewIdentifier))
             this.showTimelineViewForTimeline(this._displayedRecording.timelines.get(selectedTimelineViewIdentifier));
         else
             this.showTimelineOverview();
@@ -409,6 +448,7 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         console.assert(recording instanceof WebInspector.TimelineRecording, recording);
 
         var oldRecording = this._displayedRecording || null;
+
         if (oldRecording) {
             oldRecording.removeEventListener(WebInspector.TimelineRecording.Event.TimelineAdded, this._timelineAdded, this);
             oldRecording.removeEventListener(WebInspector.TimelineRecording.Event.TimelineRemoved, this._timelineRemoved, this);
@@ -442,11 +482,11 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
             timeline = timelineOrEvent.data.timeline;
 
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
-            return;
-
         console.assert(!this._timelineTreeElementMap.has(timeline), timeline);
 
+        if (this._viewModeForTimeline(timeline) !== WebInspector.TimelineSidebarPanel.ViewMode.Timelines)
+            return;
+
         var timelineTreeElement = new WebInspector.GeneralTreeElement([timeline.iconClassName, WebInspector.TimelineSidebarPanel.LargeIconStyleClass], timeline.displayName, null, timeline);
         var tooltip = WebInspector.UIString("Close %s timeline view").format(timeline.displayName);
         wrappedSVGDocument(platformImagePath("CloseLarge.svg"), WebInspector.TimelineSidebarPanel.CloseButtonStyleClass, tooltip, function(element) {
@@ -464,7 +504,7 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
     {
         var timeline = event.data.timeline;
         console.assert(timeline instanceof WebInspector.Timeline, timeline);
-        if (!WebInspector.TimelineManager.shouldShowViewForTimeline(timeline))
+        if (this._viewModeForTimeline(timeline) !== WebInspector.TimelineSidebarPanel.ViewMode.Timelines)
             return;
 
         console.assert(this._timelineTreeElementMap.has(timeline), timeline);
@@ -491,9 +531,10 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         }
 
         var timelineHeight = 36;
-        var eventTitleBarOffset = 51;
-        var contentElementOffset = 74;
+        var eventTitleBarOffset = 58;
+        var contentElementOffset = 81;
         var timelineCount = this._timelineTreeElementMap.size;
+
         this._timelinesContentContainerElement.style.height = (timelineHeight * timelineCount) + "px";
         this._timelineEventsTitleBarElement.style.top = (timelineHeight * timelineCount + eventTitleBarOffset) + "px";
         this.contentElement.style.top = (timelineHeight * timelineCount + contentElementOffset) + "px";
@@ -535,6 +576,54 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         }
     }
 
+    _viewModeSelected(event)
+    {
+        console.assert(event.target.selectedNavigationItem);
+        if (!event.target.selectedNavigationItem)
+            return;
+
+        var selectedNavigationItem = event.target.selectedNavigationItem;
+        var selectedByUser = true;
+        this._changeViewMode(selectedNavigationItem.identifier, selectedByUser);
+    }
+
+    _viewModeForTimeline(timeline)
+    {
+        if (timeline && timeline.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+            return WebInspector.TimelineSidebarPanel.ViewMode.RenderingFrames;
+
+        return WebInspector.TimelineSidebarPanel.ViewMode.Timelines;
+    }
+
+    _changeViewMode(mode, selectedByUser)
+    {
+        if (!this._renderingFramesSupported || this._viewMode === mode)
+            return;
+
+        this._viewMode = mode;
+        this._viewModeNavigationBar.selectedNavigationItem = this._viewMode;
+
+        if (this._viewMode === WebInspector.TimelineSidebarPanel.ViewMode.Timelines)
+            this._timelinesTreeOutline.element.classList.remove(WebInspector.NavigationSidebarPanel.ContentTreeOutlineElementHiddenStyleClassName);
+        else
+            this._timelinesTreeOutline.element.classList.add(WebInspector.NavigationSidebarPanel.ContentTreeOutlineElementHiddenStyleClassName);
+
+        if (!selectedByUser)
+            return;
+
+        if (this._viewMode === WebInspector.TimelineSidebarPanel.ViewMode.RenderingFrames) {
+            if (this._timelinesTreeOutline.selectedTreeElement)
+                this._previousTimelineSelection = this._timelinesTreeOutline.selectedTreeElement.representedObject;
+
+            console.assert(this._displayedRecording);
+            this.showTimelineViewForTimeline(this._displayedRecording.timelines.get(WebInspector.TimelineRecord.Type.RenderingFrame));
+        } else if (this._previousTimelineSelection) {
+            this.showTimelineViewForTimeline(this._previousTimelineSelection);
+            this._previousTimelineSelection = null;
+        } else
+            this.showTimelineOverview();
+    }
+
     // These methods are only used when ReplayAgent is available.
 
     _updateReplayInterfaceVisibility()
@@ -542,7 +631,7 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
         var shouldShowReplayInterface = window.ReplayAgent && WebInspector.showReplayInterfaceSetting.value;
 
         this._statusBarElement.classList.toggle(WebInspector.TimelineSidebarPanel.HiddenStyleClassName, shouldShowReplayInterface);
-        this._navigationBar.element.classList.toggle(WebInspector.TimelineSidebarPanel.HiddenStyleClassName, !shouldShowReplayInterface);
+        this._replayNavigationBar.element.classList.toggle(WebInspector.TimelineSidebarPanel.HiddenStyleClassName, !shouldShowReplayInterface);
     }
 
     _contextMenuNavigationBarOrStatusBar()
@@ -609,6 +698,11 @@ WebInspector.TimelineSidebarPanel = class TimelineSidebarPanel extends WebInspec
     }
 };
 
+WebInspector.TimelineSidebarPanel.ViewMode = {
+    Timelines: "timeline-sidebar-panel-view-mode-timelines",
+    RenderingFrames: "timeline-sidebar-panel-view-mode-frames"
+};
+
 WebInspector.TimelineSidebarPanel.HiddenStyleClassName = "hidden";
 WebInspector.TimelineSidebarPanel.StatusBarStyleClass = "status-bar";
 WebInspector.TimelineSidebarPanel.RecordGlyphStyleClass = "record-glyph";
index 9028f6f..ab97f89 100644 (file)
     <None Include="..\UserInterface\Legacy\6.0\InspectorBackendCommands.js" />
     <None Include="..\UserInterface\Legacy\7.0\InspectorBackendCommands.js" />
     <None Include="..\UserInterface\Legacy\8.0\InspectorBackendCommands.js" />
+    <None Include="..\UserInterface\LinearTimelineOverview.js" />
     <None Include="..\UserInterface\LoadInspectorBackendCommands.js" />
     <None Include="..\UserInterface\LoadLocalizedStrings.js" />
     <None Include="..\UserInterface\LogContentView.css" />
     <None Include="..\UserInterface\RemoteObject.js" />
     <None Include="..\UserInterface\RenderingFrameDetailsSidebarPanel.js" />
     <None Include="..\UserInterface\RenderingFrameTimeDataGridNode.js" />
+    <None Include="..\UserInterface\RenderingFrameTimelineOverview.js" />
     <None Include="..\UserInterface\RenderingFrameTimelineOverviewGraph.css" />
     <None Include="..\UserInterface\RenderingFrameTimelineOverviewGraph.js" />
     <None Include="..\UserInterface\RenderingFrameTimelineRecord.js" />
index ce1db64..7c6f348 100644 (file)
     <None Include="..\UserInterface\LayoutTimelineRecord.js">
       <Filter>UserInterface</Filter>
     </None>
+    <None Include="..\UserInterface\LinearTimelineOverview.js">
+      <Filter>UserInterface</Filter>
+    </None>
     <None Include="..\UserInterface\LoadInspectorBackendCommands.js">
       <Filter>UserInterface</Filter>
     </None>
     <None Include="..\UserInterface\RenderingFrameTimelineDataGridNode.js">
       <Filter>UserInterface</Filter>
     </None>
+    <None Include="..\UserInterface\RenderingFrameTimelineOverview.js">
+      <Filter>UserInterface</Filter>
+    </None>
     <None Include="..\UserInterface\RenderingFrameTimelineOverviewGraph.css">
       <Filter>UserInterface</Filter>
     </None>