<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head><meta http-equiv="content-type" content="text/html; charset=utf-8" />
<title>[197479] trunk/Source/WebInspectorUI</title>
</head>
<body>

<style type="text/css"><!--
#msg dl.meta { border: 1px #006 solid; background: #369; padding: 6px; color: #fff; }
#msg dl.meta dt { float: left; width: 6em; font-weight: bold; }
#msg dt:after { content:':';}
#msg dl, #msg dt, #msg ul, #msg li, #header, #footer, #logmsg { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt;  }
#msg dl a { font-weight: bold}
#msg dl a:link    { color:#fc3; }
#msg dl a:active  { color:#ff0; }
#msg dl a:visited { color:#cc6; }
h3 { font-family: verdana,arial,helvetica,sans-serif; font-size: 10pt; font-weight: bold; }
#msg pre { overflow: auto; background: #ffc; border: 1px #fa0 solid; padding: 6px; }
#logmsg { background: #ffc; border: 1px #fa0 solid; padding: 1em 1em 0 1em; }
#logmsg p, #logmsg pre, #logmsg blockquote { margin: 0 0 1em 0; }
#logmsg p, #logmsg li, #logmsg dt, #logmsg dd { line-height: 14pt; }
#logmsg h1, #logmsg h2, #logmsg h3, #logmsg h4, #logmsg h5, #logmsg h6 { margin: .5em 0; }
#logmsg h1:first-child, #logmsg h2:first-child, #logmsg h3:first-child, #logmsg h4:first-child, #logmsg h5:first-child, #logmsg h6:first-child { margin-top: 0; }
#logmsg ul, #logmsg ol { padding: 0; list-style-position: inside; margin: 0 0 0 1em; }
#logmsg ul { text-indent: -1em; padding-left: 1em; }#logmsg ol { text-indent: -1.5em; padding-left: 1.5em; }
#logmsg > ul, #logmsg > ol { margin: 0 0 1em 0; }
#logmsg pre { background: #eee; padding: 1em; }
#logmsg blockquote { border: 1px solid #fa0; border-left-width: 10px; padding: 1em 1em 0 1em; background: white;}
#logmsg dl { margin: 0; }
#logmsg dt { font-weight: bold; }
#logmsg dd { margin: 0; padding: 0 0 0.5em 0; }
#logmsg dd:before { content:'\00bb';}
#logmsg table { border-spacing: 0px; border-collapse: collapse; border-top: 4px solid #fa0; border-bottom: 1px solid #fa0; background: #fff; }
#logmsg table th { text-align: left; font-weight: normal; padding: 0.2em 0.5em; border-top: 1px dotted #fa0; }
#logmsg table td { text-align: right; border-top: 1px dotted #fa0; padding: 0.2em 0.5em; }
#logmsg table thead th { text-align: center; border-bottom: 1px solid #fa0; }
#logmsg table th.Corner { text-align: left; }
#logmsg hr { border: none 0; border-top: 2px dashed #fa0; height: 1px; }
#header, #footer { color: #fff; background: #636; border: 1px #300 solid; padding: 6px; }
#patch { width: 100%; }
#patch h4 {font-family: verdana,arial,helvetica,sans-serif;font-size:10pt;padding:8px;background:#369;color:#fff;margin:0;}
#patch .propset h4, #patch .binary h4 {margin:0;}
#patch pre {padding:0;line-height:1.2em;margin:0;}
#patch .diff {width:100%;background:#eee;padding: 0 0 10px 0;overflow:auto;}
#patch .propset .diff, #patch .binary .diff  {padding:10px 0;}
#patch span {display:block;padding:0 10px;}
#patch .modfile, #patch .addfile, #patch .delfile, #patch .propset, #patch .binary, #patch .copfile {border:1px solid #ccc;margin:10px 0;}
#patch ins {background:#dfd;text-decoration:none;display:block;padding:0 10px;}
#patch del {background:#fdd;text-decoration:none;display:block;padding:0 10px;}
#patch .lines, .info {color:#888;background:#fff;}
--></style>
<div id="msg">
<dl class="meta">
<dt>Revision</dt> <dd><a href="http://trac.webkit.org/projects/webkit/changeset/197479">197479</a></dd>
<dt>Author</dt> <dd>mattbaker@apple.com</dd>
<dt>Date</dt> <dd>2016-03-02 16:34:59 -0800 (Wed, 02 Mar 2016)</dd>
</dl>

<h3>Log Message</h3>
<pre>Web Inspector: Timelines UI redesign: relocate recording controls to TimelineTabContentView's content browser
https://bugs.webkit.org/show_bug.cgi?id=153532
&lt;rdar://problem/24361611&gt;

Reviewed by Timothy Hatcher.

This patch shifts UI controller responsibilities from the sidebar panel
to the tab content view. Controls for starting/stopping the recording and
switching view modes are now located in the tab's navigation bar, as is
the hidden tree outline of open timeline recordings.

* Localizations/en.lproj/localizedStrings.js:
New UI strings. Renamed view-mode radio buttons located from the sidebar
to &quot;Events&quot; and &quot;Frames&quot;. UI for switching modes isn't final, and the
labels may change or be removed entirely in favor of image-only buttons.

* UserInterface/Main.html:
New file.

* UserInterface/Views/ContentBrowserTabContentView.js:
(WebInspector.ContentBrowserTabContentView.prototype.contentBrowserTreeElementForRepresentedObject):
(WebInspector.ContentBrowserTabContentView.prototype.treeElementForRepresentedObject):
Allow subclasses to override behavior for retrieving the tree element
for a represented object. Default behavior delegates the implementation
to the navigation sidebar.

(WebInspector.ContentBrowserTabContentView.prototype._contentBrowserCurrentContentViewDidChange):
(WebInspector.ContentBrowserTabContentView.prototype._revealAndSelectRepresentedObject):
(WebInspector.ContentBrowserTabContentView):
(WebInspector.ContentBrowserTabContentView.prototype._revealAndSelectRepresentedObjectInNavigationSidebar): Deleted.
Renamed to _revealAndSelectRepresentedObject as it's no longer specific
to the sidebar.

* UserInterface/Views/TabContentView.js:
(WebInspector.TabContentView):
(WebInspector.TabContentView.prototype.restoreStateFromCookie):
(WebInspector.TabContentView.prototype.saveStateToCookie):
A navigation sidebar shouldn't be required to save/restore cookie state.

* UserInterface/Views/TimelineTabContentView.css: Added.
(.timeline.tab.content-view .navigation-bar &gt; .item.toggle-navigation-sidebar.activate.button):
(.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop):
(.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:hover):
(.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:active):
(.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop *):
(.timeline.tab.content-view .navigation-bar &gt; .item.radio):
Styles for new navigation items: record button and view mode radio buttons.

* UserInterface/Views/TimelineTabContentView.js:
Logic for maintaining the timeline recording hierarchy and the state
of the active recording has been added to the tab content view.

(WebInspector.TimelineTabContentView):
(WebInspector.TimelineTabContentView.prototype.shown):
(WebInspector.TimelineTabContentView.prototype.hidden):
(WebInspector.TimelineTabContentView.prototype.canShowRepresentedObject):
Objects other than recordings are no longer shown in the tab's content
browser. Displaying other objects (such as timeline resources) in the
content browser will be addressed in a follow-up patch: https://bugs.webkit.org/show_bug.cgi?id=154920.

(WebInspector.TimelineTabContentView.prototype.get supportsSplitContentBrowser):
(WebInspector.TimelineTabContentView.prototype.restoreFromCookie):
(WebInspector.TimelineTabContentView.prototype.saveToCookie):
Persist view state that was previously located in the sidebar.

(WebInspector.TimelineTabContentView.prototype.treeElementForRepresentedObject):
Implements logic previously limited to the navigation sidebar. Only tree
elements for timeline recordings are supported, since other represented
objects (timeline resources) no longer have content tree outline tree elements.

(WebInspector.TimelineTabContentView.prototype._capturingStartedOrStopped):
(WebInspector.TimelineTabContentView.prototype._toggleRecordingOnSpacebar):
(WebInspector.TimelineTabContentView.prototype._toggleNewRecordingOnSpacebar):
(WebInspector.TimelineTabContentView.prototype._toggleRecording):
(WebInspector.TimelineTabContentView.prototype._recordButtonClicked):
(WebInspector.TimelineTabContentView.prototype._recordingsTreeSelectionDidChange):
(WebInspector.TimelineTabContentView.prototype._recordingCreated):
(WebInspector.TimelineTabContentView.prototype._addRecording):
(WebInspector.TimelineTabContentView.prototype._recordingCountChanged):
(WebInspector.TimelineTabContentView.prototype._recordingLoaded):
Implementations copied from the sidebar panel.

(WebInspector.TimelineTabContentView.prototype._recordingSelected):
Implementation similar to that which existed in the sidebar panel, except
that logic related to instruments isn't needed. Updates to timeline view
filters will be implemented in a follow-up patch: https://bugs.webkit.org/show_bug.cgi?id=154924.

(WebInspector.TimelineTabContentView.prototype._viewModeSelected):
This method is now limited to the handling of the radio button event only.
Additional logic which existed in the sidebar panel's implementation has
been pushed into _changeViewMode, which does the actual work of toggling
view modes.

(WebInspector.TimelineTabContentView.prototype._changeViewMode):
Updates the current view mode state. If triggered by a user selection (was
called by the radio button event handler), the correct timeline view for
the new mode is shown.

(WebInspector.TimelineTabContentView.prototype._showTimelineViewForType):
Helper function for showing the view for the specified timeline type, if
the timeline exists in the current recording. Otherwise the overview timeline
view is displayed.

(WebInspector.TimelineTabContentView.prototype._displayedContentViewNavigationItemsDidChange):
Keep the view mode in sync with the content browser.

(WebInspector.TimelineTabContentView.prototype._getTimelineForCurrentContentView):
Helper function for getting the currently displayed timeline.</pre>

<h3>Modified Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIChangeLog">trunk/Source/WebInspectorUI/ChangeLog</a></li>
<li><a href="#trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs">trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceMainhtml">trunk/Source/WebInspectorUI/UserInterface/Main.html</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsContentBrowserTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js</a></li>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewjs">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js</a></li>
</ul>

<h3>Added Paths</h3>
<ul>
<li><a href="#trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewcss">trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.css</a></li>
</ul>

</div>
<div id="patch">
<h3>Diff</h3>
<a id="trunkSourceWebInspectorUIChangeLog"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/ChangeLog (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/ChangeLog        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/ChangeLog        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -1,5 +1,116 @@
</span><span class="cx"> 2016-03-02  Matt Baker  &lt;mattbaker@apple.com&gt;
</span><span class="cx"> 
</span><ins>+        Web Inspector: Timelines UI redesign: relocate recording controls to TimelineTabContentView's content browser
+        https://bugs.webkit.org/show_bug.cgi?id=153532
+        &lt;rdar://problem/24361611&gt;
+
+        Reviewed by Timothy Hatcher.
+
+        This patch shifts UI controller responsibilities from the sidebar panel
+        to the tab content view. Controls for starting/stopping the recording and
+        switching view modes are now located in the tab's navigation bar, as is
+        the hidden tree outline of open timeline recordings.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        New UI strings. Renamed view-mode radio buttons located from the sidebar
+        to &quot;Events&quot; and &quot;Frames&quot;. UI for switching modes isn't final, and the
+        labels may change or be removed entirely in favor of image-only buttons.
+
+        * UserInterface/Main.html:
+        New file.
+
+        * UserInterface/Views/ContentBrowserTabContentView.js:
+        (WebInspector.ContentBrowserTabContentView.prototype.contentBrowserTreeElementForRepresentedObject):
+        (WebInspector.ContentBrowserTabContentView.prototype.treeElementForRepresentedObject):
+        Allow subclasses to override behavior for retrieving the tree element
+        for a represented object. Default behavior delegates the implementation
+        to the navigation sidebar.
+
+        (WebInspector.ContentBrowserTabContentView.prototype._contentBrowserCurrentContentViewDidChange):
+        (WebInspector.ContentBrowserTabContentView.prototype._revealAndSelectRepresentedObject):
+        (WebInspector.ContentBrowserTabContentView):
+        (WebInspector.ContentBrowserTabContentView.prototype._revealAndSelectRepresentedObjectInNavigationSidebar): Deleted.
+        Renamed to _revealAndSelectRepresentedObject as it's no longer specific
+        to the sidebar.
+
+        * UserInterface/Views/TabContentView.js:
+        (WebInspector.TabContentView):
+        (WebInspector.TabContentView.prototype.restoreStateFromCookie):
+        (WebInspector.TabContentView.prototype.saveStateToCookie):
+        A navigation sidebar shouldn't be required to save/restore cookie state.
+
+        * UserInterface/Views/TimelineTabContentView.css: Added.
+        (.timeline.tab.content-view .navigation-bar &gt; .item.toggle-navigation-sidebar.activate.button):
+        (.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop):
+        (.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:hover):
+        (.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:active):
+        (.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop *):
+        (.timeline.tab.content-view .navigation-bar &gt; .item.radio):
+        Styles for new navigation items: record button and view mode radio buttons.
+
+        * UserInterface/Views/TimelineTabContentView.js:
+        Logic for maintaining the timeline recording hierarchy and the state
+        of the active recording has been added to the tab content view.
+
+        (WebInspector.TimelineTabContentView):
+        (WebInspector.TimelineTabContentView.prototype.shown):
+        (WebInspector.TimelineTabContentView.prototype.hidden):
+        (WebInspector.TimelineTabContentView.prototype.canShowRepresentedObject):
+        Objects other than recordings are no longer shown in the tab's content
+        browser. Displaying other objects (such as timeline resources) in the
+        content browser will be addressed in a follow-up patch: https://bugs.webkit.org/show_bug.cgi?id=154920.
+
+        (WebInspector.TimelineTabContentView.prototype.get supportsSplitContentBrowser):
+        (WebInspector.TimelineTabContentView.prototype.restoreFromCookie):
+        (WebInspector.TimelineTabContentView.prototype.saveToCookie):
+        Persist view state that was previously located in the sidebar.
+
+        (WebInspector.TimelineTabContentView.prototype.treeElementForRepresentedObject):
+        Implements logic previously limited to the navigation sidebar. Only tree
+        elements for timeline recordings are supported, since other represented
+        objects (timeline resources) no longer have content tree outline tree elements.
+
+        (WebInspector.TimelineTabContentView.prototype._capturingStartedOrStopped):
+        (WebInspector.TimelineTabContentView.prototype._toggleRecordingOnSpacebar):
+        (WebInspector.TimelineTabContentView.prototype._toggleNewRecordingOnSpacebar):
+        (WebInspector.TimelineTabContentView.prototype._toggleRecording):
+        (WebInspector.TimelineTabContentView.prototype._recordButtonClicked):
+        (WebInspector.TimelineTabContentView.prototype._recordingsTreeSelectionDidChange):
+        (WebInspector.TimelineTabContentView.prototype._recordingCreated):
+        (WebInspector.TimelineTabContentView.prototype._addRecording):
+        (WebInspector.TimelineTabContentView.prototype._recordingCountChanged):
+        (WebInspector.TimelineTabContentView.prototype._recordingLoaded):
+        Implementations copied from the sidebar panel.
+
+        (WebInspector.TimelineTabContentView.prototype._recordingSelected):
+        Implementation similar to that which existed in the sidebar panel, except
+        that logic related to instruments isn't needed. Updates to timeline view
+        filters will be implemented in a follow-up patch: https://bugs.webkit.org/show_bug.cgi?id=154924.
+
+        (WebInspector.TimelineTabContentView.prototype._viewModeSelected):
+        This method is now limited to the handling of the radio button event only.
+        Additional logic which existed in the sidebar panel's implementation has
+        been pushed into _changeViewMode, which does the actual work of toggling
+        view modes.
+
+        (WebInspector.TimelineTabContentView.prototype._changeViewMode):
+        Updates the current view mode state. If triggered by a user selection (was
+        called by the radio button event handler), the correct timeline view for
+        the new mode is shown.
+
+        (WebInspector.TimelineTabContentView.prototype._showTimelineViewForType):
+        Helper function for showing the view for the specified timeline type, if
+        the timeline exists in the current recording. Otherwise the overview timeline
+        view is displayed.
+
+        (WebInspector.TimelineTabContentView.prototype._displayedContentViewNavigationItemsDidChange):
+        Keep the view mode in sync with the content browser.
+
+        (WebInspector.TimelineTabContentView.prototype._getTimelineForCurrentContentView):
+        Helper function for getting the currently displayed timeline.
+
+2016-03-02  Matt Baker  &lt;mattbaker@apple.com&gt;
+
</ins><span class="cx">         Web Inspector: Timelines UI redesign: add the timelines tree outline to the TimelineOverview
</span><span class="cx">         https://bugs.webkit.org/show_bug.cgi?id=153034
</span><span class="cx">         &lt;rdar://problem/24195628&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUILocalizationsenlprojlocalizedStringsjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -291,6 +291,7 @@
</span><span class="cx"> localizedStrings[&quot;Evaluate JavaScript&quot;] = &quot;Evaluate JavaScript&quot;;
</span><span class="cx"> localizedStrings[&quot;Event Dispatched&quot;] = &quot;Event Dispatched&quot;;
</span><span class="cx"> localizedStrings[&quot;Event Listeners&quot;] = &quot;Event Listeners&quot;;
</span><ins>+localizedStrings[&quot;Events&quot;] = &quot;Events&quot;;
</ins><span class="cx"> localizedStrings[&quot;Exception with thrown value: %s&quot;] = &quot;Exception with thrown value: %s&quot;;
</span><span class="cx"> localizedStrings[&quot;Expand columns&quot;] = &quot;Expand columns&quot;;
</span><span class="cx"> localizedStrings[&quot;Expanded&quot;] = &quot;Expanded&quot;;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceMainhtml"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -163,6 +163,7 @@
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineRecordingContentView.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineRuler.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineSidebarPanel.css&quot;&gt;
</span><ins>+    &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineTabContentView.css&quot;&gt;
</ins><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TimelineView.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/Toolbar.css&quot;&gt;
</span><span class="cx">     &lt;link rel=&quot;stylesheet&quot; href=&quot;Views/TreeElementStatusButton.css&quot;&gt;
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsContentBrowserTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowserTabContentView.js        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -189,11 +189,21 @@
</span><span class="cx"> 
</span><span class="cx">     contentBrowserTreeElementForRepresentedObject(contentBrowser, representedObject)
</span><span class="cx">     {
</span><del>-        if (this.navigationSidebarPanel)
-            return this.navigationSidebarPanel.treeElementForRepresentedObject(representedObject);
-        return null;
</del><ins>+        return this.treeElementForRepresentedObject(representedObject);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><ins>+    // Protected
+
+    treeElementForRepresentedObject(representedObject)
+    {
+        // Can be overriden by subclasses.
+
+        if (!this.navigationSidebarPanel)
+            return null;
+
+        return this.navigationSidebarPanel.treeElementForRepresentedObject(representedObject);
+     }
+
</ins><span class="cx">     // Private
</span><span class="cx"> 
</span><span class="cx">     _navigationSidebarCollapsedStateDidChange(event)
</span><span class="lines">@@ -231,31 +241,30 @@
</span><span class="cx"> 
</span><span class="cx">     _contentBrowserCurrentContentViewDidChange(event)
</span><span class="cx">     {
</span><del>-        var currentContentView = this._contentBrowser.currentContentView;
</del><ins>+        let currentContentView = this._contentBrowser.currentContentView;
</ins><span class="cx">         if (!currentContentView)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        this._revealAndSelectRepresentedObjectInNavigationSidebar(currentContentView.representedObject);
</del><ins>+        this._revealAndSelectRepresentedObject(currentContentView.representedObject);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    _revealAndSelectRepresentedObjectInNavigationSidebar(representedObject)
</del><ins>+    _revealAndSelectRepresentedObject(representedObject)
</ins><span class="cx">     {
</span><del>-        if (!this.navigationSidebarPanel)
-            return;
-
-        // If a tree outline is processing a selection currently then we can assume the selection does not
-        // need to be changed. This is needed to allow breakpoint and call frame tree elements to be selected
-        // without jumping back to selecting the resource tree element.
-        for (var contentTreeOutline of this.navigationSidebarPanel.visibleContentTreeOutlines) {
-            if (contentTreeOutline.processingSelectionChange)
-                return;
</del><ins>+        if (this.navigationSidebarPanel) {
+            // If a tree outline is processing a selection currently then we can assume the selection does not
+            // need to be changed. This is needed to allow breakpoint and call frame tree elements to be selected
+            // without jumping back to selecting the resource tree element.
+            for (let contentTreeOutline of this.navigationSidebarPanel.visibleContentTreeOutlines) {
+                if (contentTreeOutline.processingSelectionChange)
+                    return;
+            }
</ins><span class="cx">         }
</span><span class="cx"> 
</span><del>-        var treeElement = this.navigationSidebarPanel.treeElementForRepresentedObject(representedObject);
</del><ins>+        let treeElement = this.treeElementForRepresentedObject(representedObject);
</ins><span class="cx"> 
</span><span class="cx">         if (treeElement)
</span><span class="cx">             treeElement.revealAndSelect(true, false, true, true);
</span><del>-        else if (this.navigationSidebarPanel.contentTreeOutline.selectedTreeElement)
</del><ins>+        else if (this.navigationSidebarPanel &amp;&amp; this.navigationSidebarPanel.contentTreeOutline.selectedTreeElement)
</ins><span class="cx">             this.navigationSidebarPanel.contentTreeOutline.selectedTreeElement.deselect(true);
</span><span class="cx">     }
</span><span class="cx"> };
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TabContentView.js        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -131,9 +131,6 @@
</span><span class="cx"> 
</span><span class="cx">     restoreStateFromCookie(restorationType)
</span><span class="cx">     {
</span><del>-        if (!this.navigationSidebarPanel)
-            return;
-
</del><span class="cx">         if (!this.visible) {
</span><span class="cx">             this._shouldRestoreStateWhenShown = true;
</span><span class="cx">             return;
</span><span class="lines">@@ -147,19 +144,26 @@
</span><span class="cx">         else if (restorationType === WebInspector.StateRestorationType.Navigation)
</span><span class="cx">             relaxMatchDelay = 2000;
</span><span class="cx"> 
</span><del>-        this.navigationSidebarPanel.restoreStateFromCookie(this._cookieSetting.value || {}, relaxMatchDelay);
</del><ins>+        let cookie = this._cookieSetting.value || {};
+
+        if (this.navigationSidebarPanel)
+            this.navigationSidebarPanel.restoreStateFromCookie(cookie, relaxMatchDelay);
+
+        this.restoreFromCookie(cookie);
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    saveStateToCookie()
</del><ins>+    saveStateToCookie(cookie)
</ins><span class="cx">     {
</span><del>-        if (!this.navigationSidebarPanel)
-            return;
-
</del><span class="cx">         if (this._shouldRestoreStateWhenShown)
</span><span class="cx">             return;
</span><span class="cx"> 
</span><del>-        var cookie = {};
-        this.navigationSidebarPanel.saveStateToCookie(cookie);
</del><ins>+        cookie = cookie || {};
+
+        if (this.navigationSidebarPanel)
+            this.navigationSidebarPanel.saveStateToCookie(cookie);
+
+        this.saveToCookie(cookie);
+
</ins><span class="cx">         this._cookieSetting.value = cookie;
</span><span class="cx">     }
</span><span class="cx"> 
</span></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewcss"></a>
<div class="addfile"><h4>Added: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.css (0 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.css                                (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.css        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -0,0 +1,46 @@
</span><ins>+/*
+ * Copyright (C) 2016 Apple Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop {
+    /* Workaround for background image clipping issue on non-retina machines. See http://webkit.org/b/147346. */
+    filter: brightness(100%);
+}
+
+.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:hover {
+    filter: brightness(95%);
+}
+
+.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop:active {
+    filter: brightness(80%);
+}
+
+.timeline.tab.content-view .navigation-bar &gt; .item.record-start-stop * {
+    pointer-events: none;
+}
+
+.timeline.tab.content-view .navigation-bar &gt; .item.radio {
+    margin-top: 5px;
+    height: 17px;
+}
</ins></span></pre></div>
<a id="trunkSourceWebInspectorUIUserInterfaceViewsTimelineTabContentViewjs"></a>
<div class="modfile"><h4>Modified: trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js (197478 => 197479)</h4>
<pre class="diff"><span>
<span class="info">--- trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js        2016-03-03 00:34:19 UTC (rev 197478)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/TimelineTabContentView.js        2016-03-03 00:34:59 UTC (rev 197479)
</span><span class="lines">@@ -32,6 +32,62 @@
</span><span class="cx">         let detailsSidebarPanels = [WebInspector.resourceDetailsSidebarPanel, WebInspector.probeDetailsSidebarPanel];
</span><span class="cx"> 
</span><span class="cx">         super(identifier || &quot;timeline&quot;, &quot;timeline&quot;, tabBarItem, WebInspector.TimelineSidebarPanel, detailsSidebarPanels);
</span><ins>+
+        // Maintain an invisible tree outline containing tree elements for all recordings.
+        // The visible recording's tree element is selected when the content view changes.
+        this._recordingTreeElementMap = new Map;
+        this._recordingsTreeOutline = new WebInspector.TreeOutline;
+        this._recordingsTreeOutline.addEventListener(WebInspector.TreeOutline.Event.SelectionDidChange, this._recordingsTreeSelectionDidChange, this);
+
+        this._toggleRecordingShortcut = new WebInspector.KeyboardShortcut(null, WebInspector.KeyboardShortcut.Key.Space, this._toggleRecordingOnSpacebar.bind(this));
+        this._toggleRecordingShortcut.implicitlyPreventsDefault = false;
+        this._toggleRecordingShortcut.disabled = true;
+
+        this._toggleNewRecordingShortcut = new WebInspector.KeyboardShortcut(WebInspector.KeyboardShortcut.Modifier.Shift, WebInspector.KeyboardShortcut.Key.Space, this._toggleNewRecordingOnSpacebar.bind(this));
+        this._toggleNewRecordingShortcut.implicitlyPreventsDefault = false;
+        this._toggleNewRecordingShortcut.disabled = true;
+
+        let toolTip = WebInspector.UIString(&quot;Start recording (%s)\nCreate new recording (%s)&quot;).format(this._toggleRecordingShortcut.displayName, this._toggleNewRecordingShortcut.displayName);
+        let altToolTip = WebInspector.UIString(&quot;Stop recording (%s)&quot;).format(this._toggleRecordingShortcut.displayName);
+        this._recordButton = new WebInspector.ToggleButtonNavigationItem(&quot;record-start-stop&quot;, toolTip, altToolTip, &quot;Images/Record.svg&quot;, &quot;Images/Stop.svg&quot;, 13, 13);
+        this._recordButton.addEventListener(WebInspector.ButtonNavigationItem.Event.Clicked, this._recordButtonClicked, this);
+
+        this.contentBrowser.navigationBar.insertNavigationItem(this._recordButton, 0);
+
+        if (WebInspector.FPSInstrument.supported()) {
+            let timelinesNavigationItem = new WebInspector.RadioButtonNavigationItem(WebInspector.TimelineOverview.ViewMode.Timelines, WebInspector.UIString(&quot;Events&quot;));
+            let renderingFramesNavigationItem = new WebInspector.RadioButtonNavigationItem(WebInspector.TimelineOverview.ViewMode.RenderingFrames, WebInspector.UIString(&quot;Frames&quot;));
+
+            this.contentBrowser.navigationBar.insertNavigationItem(timelinesNavigationItem, 1);
+            this.contentBrowser.navigationBar.insertNavigationItem(renderingFramesNavigationItem, 2);
+
+            this.contentBrowser.navigationBar.addEventListener(WebInspector.NavigationBar.Event.NavigationItemSelected, this._viewModeSelected, this);
+        }
+
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.RecordingCreated, this._recordingCreated, this);
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.RecordingLoaded, this._recordingLoaded, this);
+
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStarted, this._capturingStartedOrStopped, this);
+        WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.Event.CapturingStopped, this._capturingStartedOrStopped, this);
+
+        this._displayedRecording = null;
+        this._displayedContentView = null;
+        this._viewMode = null;
+        this._previousSelectedTimelineType = null;
+
+        const selectedByUser = false;
+        this._changeViewMode(WebInspector.TimelineOverview.ViewMode.Timelines, selectedByUser);
+
+        for (let recording of WebInspector.timelineManager.recordings)
+            this._addRecording(recording);
+
+        this._recordingCountChanged();
+
+        if (WebInspector.timelineManager.activeRecording)
+            this._recordingLoaded();
+
+        // Explicitly update the path for the navigation bar to prevent it from showing up as blank.
+        this.contentBrowser.updateHierarchicalPathForCurrentContentView();
</ins><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     // Static
</span><span class="lines">@@ -205,6 +261,9 @@
</span><span class="cx">     {
</span><span class="cx">         super.shown();
</span><span class="cx"> 
</span><ins>+        this._toggleRecordingShortcut.disabled = false;
+        this._toggleNewRecordingShortcut.disabled = false;
+
</ins><span class="cx">         WebInspector.timelineManager.autoCaptureOnPageLoad = true;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="lines">@@ -212,25 +271,275 @@
</span><span class="cx">     {
</span><span class="cx">         super.hidden();
</span><span class="cx"> 
</span><ins>+        this._toggleRecordingShortcut.disabled = true;
+        this._toggleNewRecordingShortcut.disabled = true;
+
</ins><span class="cx">         WebInspector.timelineManager.autoCaptureOnPageLoad = false;
</span><span class="cx">     }
</span><span class="cx"> 
</span><span class="cx">     canShowRepresentedObject(representedObject)
</span><span class="cx">     {
</span><ins>+        return representedObject instanceof WebInspector.TimelineRecording;
+    }
+
+    get supportsSplitContentBrowser()
+    {
+        return false;
+    }
+
+    // Protected
+
+    restoreFromCookie(cookie)
+    {
+        console.assert(cookie);
+        console.assert(this._displayedContentView);
+
+        this._restoredShowingTimelineRecordingContentView = cookie[WebInspector.TimelineTabContentView.ShowingTimelineRecordingContentViewCookieKey];
+        if (!this._restoredShowingTimelineRecordingContentView)
+            return;
+
+        let selectedTimelineViewIdentifier = cookie[WebInspector.TimelineTabContentView.SelectedTimelineViewIdentifierCookieKey];
+        if (selectedTimelineViewIdentifier === WebInspector.TimelineRecord.Type.RenderingFrame &amp;&amp; !WebInspector.FPSInstrument.supported())
+            selectedTimelineViewIdentifier = null;
+
+        this._showTimelineViewForType(selectedTimelineViewIdentifier);
+
+        super.restoreFromCookie(cookie);
+    }
+
+    saveToCookie(cookie)
+    {
+        console.assert(cookie);
+
+        cookie[WebInspector.TimelineTabContentView.ShowingTimelineRecordingContentViewCookieKey] = this.contentBrowser.currentContentView instanceof WebInspector.TimelineRecordingContentView;
+
+        if (this._viewMode === WebInspector.TimelineOverview.ViewMode.RenderingFrames)
+            cookie[WebInspector.TimelineTabContentView.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineRecord.Type.RenderingFrame;
+        else {
+            let selectedTimeline = this._getTimelineForCurrentContentView();
+            if (selectedTimeline)
+                cookie[WebInspector.TimelineTabContentView.SelectedTimelineViewIdentifierCookieKey] = selectedTimeline.type;
+            else
+                cookie[WebInspector.TimelineTabContentView.SelectedTimelineViewIdentifierCookieKey] = WebInspector.TimelineTabContentView.OverviewTimelineIdentifierCookieValue;
+        }
+
+        super.saveToCookie(cookie);
+    }
+
+    treeElementForRepresentedObject(representedObject)
+    {
+        // This can be called by the base class constructor before the map is created.
+        if (!this._recordingTreeElementMap)
+            return null;
+
</ins><span class="cx">         if (representedObject instanceof WebInspector.TimelineRecording)
</span><del>-            return true;
</del><ins>+            return this._recordingTreeElementMap.get(representedObject);
</ins><span class="cx"> 
</span><del>-        // Only support showing a resource or script if we have that represented object in the sidebar.
-        if (representedObject instanceof WebInspector.Resource || representedObject instanceof WebInspector.Script)
-            return !!this.navigationSidebarPanel.treeElementForRepresentedObject(representedObject);
</del><ins>+        return null;
+    }
</ins><span class="cx"> 
</span><del>-        return false;
</del><ins>+    // Private
+
+    _capturingStartedOrStopped(event)
+    {
+        let isCapturing = WebInspector.timelineManager.isCapturing();
+        this._recordButton.toggled = isCapturing;
</ins><span class="cx">     }
</span><span class="cx"> 
</span><del>-    get supportsSplitContentBrowser()
</del><ins>+    _toggleRecordingOnSpacebar(event)
</ins><span class="cx">     {
</span><del>-        return false;
</del><ins>+        if (WebInspector.isEventTargetAnEditableField(event))
+            return;
+
+        this._toggleRecording();
+
+        event.preventDefault();
</ins><span class="cx">     }
</span><ins>+
+    _toggleNewRecordingOnSpacebar(event)
+    {
+        if (WebInspector.isEventTargetAnEditableField(event))
+            return;
+
+        this._toggleRecording(true);
+
+        event.preventDefault();
+    }
+
+    _toggleRecording(shouldCreateRecording)
+    {
+        let isCapturing = WebInspector.timelineManager.isCapturing();
+        this._recordButton.toggled = isCapturing;
+
+        if (isCapturing)
+            WebInspector.timelineManager.stopCapturing();
+        else {
+            WebInspector.timelineManager.startCapturing(shouldCreateRecording);
+            // Show the timeline to which events will be appended.
+            this._recordingLoaded();
+        }
+    }
+
+    _recordButtonClicked(event)
+    {
+        this._recordButton.toggled = !WebInspector.timelineManager.isCapturing();
+        this._toggleRecording(event.shiftKey);
+    }
+
+    _recordingsTreeSelectionDidChange(event)
+    {
+        let treeElement = event.data.selectedElement;
+        if (!treeElement)
+            return;
+
+        console.assert(treeElement.representedObject instanceof WebInspector.TimelineRecording);
+
+        this._recordingSelected(treeElement.representedObject);
+    }
+
+    _recordingCreated(event)
+    {
+        this._addRecording(event.data.recording)
+        this._recordingCountChanged();
+    }
+
+    _addRecording(recording)
+    {
+        console.assert(recording instanceof WebInspector.TimelineRecording, recording);
+
+        let recordingTreeElement = new WebInspector.GeneralTreeElement(WebInspector.TimelineSidebarPanel.StopwatchIconStyleClass, recording.displayName, null, recording);
+        this._recordingTreeElementMap.set(recording, recordingTreeElement);
+        this._recordingsTreeOutline.appendChild(recordingTreeElement);
+    }
+
+    _recordingCountChanged()
+    {
+        let previousTreeElement = null;
+        for (let treeElement of this._recordingTreeElementMap.values()) {
+            if (previousTreeElement) {
+                previousTreeElement.nextSibling = treeElement;
+                treeElement.previousSibling = previousTreeElement;
+            }
+
+            previousTreeElement = treeElement;
+        }
+    }
+
+    _recordingSelected(recording)
+    {
+        console.assert(recording instanceof WebInspector.TimelineRecording, recording);
+
+        this._displayedRecording = recording;
+
+        // Save the current state incase we need to restore it to a new recording.
+        let cookie = {};
+        this.saveToCookie(cookie);
+
+        if (this._displayedContentView)
+            this._displayedContentView.removeEventListener(WebInspector.ContentView.Event.NavigationItemsDidChange, this._displayedContentViewNavigationItemsDidChange, this);
+
+        // Try to get the recording content view if it exists already, if it does we don't want to restore the cookie.
+        let onlyExisting = true;
+        this._displayedContentView = this.contentBrowser.contentViewForRepresentedObject(this._displayedRecording, onlyExisting);
+        if (this._displayedContentView) {
+            this._displayedContentView.addEventListener(WebInspector.ContentView.Event.NavigationItemsDidChange, this._displayedContentViewNavigationItemsDidChange, this);
+
+            // Show the timeline that was being shown to update the sidebar tree state.
+            let currentTimelineView = this._displayedContentView.currentTimelineView;
+            let timelineType = currentTimelineView &amp;&amp; currentTimelineView.representedObject instanceof WebInspector.Timeline ? currentTimelineView.type : null;
+            this._showTimelineViewForType(timelineType);
+
+            return;
+        }
+
+        onlyExisting = false;
+        this._displayedContentView = this.contentBrowser.contentViewForRepresentedObject(this._displayedRecording, onlyExisting);
+        if (this._displayedContentView)
+            this._displayedContentView.addEventListener(WebInspector.ContentView.Event.NavigationItemsDidChange, this._displayedContentViewNavigationItemsDidChange, this);
+
+        // Restore the cookie to carry over the previous recording view state to the new recording.
+        this.restoreFromCookie(cookie);
+    }
+
+    _recordingLoaded(event)
+    {
+        this._recordingSelected(WebInspector.timelineManager.activeRecording);
+    }
+
+    _viewModeSelected(event)
+    {
+        let selectedNavigationItem = event.target.selectedNavigationItem;
+        console.assert(selectedNavigationItem);
+        if (!selectedNavigationItem)
+            return;
+
+        const selectedByUser = true;
+        this._changeViewMode(selectedNavigationItem.identifier, selectedByUser);
+    }
+
+    _changeViewMode(mode, selectedByUser)
+    {
+        console.assert(WebInspector.FPSInstrument.supported());
+
+        if (this._viewMode === mode)
+            return;
+
+        this._viewMode = mode;
+        this.contentBrowser.navigationBar.selectedNavigationItem = this._viewMode;
+
+        if (!selectedByUser)
+            return;
+
+        let timelineType = this._previousSelectedTimelineType;
+        if (this._viewMode === WebInspector.TimelineOverview.ViewMode.RenderingFrames) {
+            let timeline = this._getTimelineForCurrentContentView();
+            this._previousSelectedTimelineType = timeline ? timeline.type : null;
+            timelineType = WebInspector.TimelineRecord.Type.RenderingFrame;
+        }
+
+        this._showTimelineViewForType(timelineType);
+    }
+
+    _showTimelineViewForType(timelineType)
+    {
+        if (timelineType) {
+            let timeline = this._displayedRecording.timelines.get(timelineType);
+            console.assert(timeline, &quot;Cannot show timeline because it does not belong to the shown recording.&quot;, timelineType);
+            if (!timeline)
+                return;
+
+            this._displayedContentView.showTimelineViewForTimeline(timeline);
+        } else
+            this._displayedContentView.showOverviewTimelineView();
+
+        if (this.contentBrowser.currentContentView !== this._displayedContentView)
+            this.contentBrowser.showContentView(this._displayedContentView);
+    }
+
+    _displayedContentViewNavigationItemsDidChange(event)
+    {
+        let timeline = this._getTimelineForCurrentContentView();
+        let newViewMode = WebInspector.TimelineOverview.ViewMode.Timelines;
+        if (timeline &amp;&amp; timeline.type === WebInspector.TimelineRecord.Type.RenderingFrame)
+            newViewMode = WebInspector.TimelineOverview.ViewMode.RenderingFrames;
+
+        const selectedByUser = false;
+        this._changeViewMode(newViewMode, selectedByUser);
+    }
+
+    _getTimelineForCurrentContentView()
+    {
+        let currentContentView = this.contentBrowser.currentContentView;
+        if (!(currentContentView instanceof WebInspector.TimelineRecordingContentView))
+            return null;
+
+        let timelineView = currentContentView.currentTimelineView;
+        return (timelineView &amp;&amp; timelineView.representedObject instanceof WebInspector.Timeline) ? timelineView.representedObject : null;
+    }
</ins><span class="cx"> };
</span><span class="cx"> 
</span><span class="cx"> WebInspector.TimelineTabContentView.Type = &quot;timeline&quot;;
</span><ins>+
+WebInspector.TimelineTabContentView.ShowingTimelineRecordingContentViewCookieKey = &quot;timeline-sidebar-panel-showing-timeline-recording-content-view&quot;;
+WebInspector.TimelineTabContentView.SelectedTimelineViewIdentifierCookieKey = &quot;timeline-sidebar-panel-selected-timeline-view-identifier&quot;;
+WebInspector.TimelineTabContentView.OverviewTimelineIdentifierCookieValue = &quot;overview&quot;;
</ins></span></pre>
</div>
</div>

</body>
</html>