Web Inspector: Timelines UI redesign: show content tree outline records in timeline...
authormattbaker@apple.com <mattbaker@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Mar 2016 03:45:50 +0000 (03:45 +0000)
committermattbaker@apple.com <mattbaker@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 3 Mar 2016 03:45:50 +0000 (03:45 +0000)
https://bugs.webkit.org/show_bug.cgi?id=153032
<rdar://problem/24195317>

Reviewed by Timothy Hatcher.

This patch relocates the data shown in the Timelines navigation sidebar content tree outline
to a new grid column in each TimelineDataGrid. Logic for creating subtitles, goto arrow buttons,
and status elements (the progress spinner used for network resources) has been replicated in
the appropriate TimelineDataGridNode classes.

Duplicate logic contained in TimelineRecordTreeElement classes is left in place for now, but
will be removed in <https://webkit.org/b/153036>.

* UserInterface/Views/DataGrid.css:
(.data-grid td.error):
Use --error-text-color CSS variable.

* UserInterface/Views/DataGrid.js:
Removed GoToArrowClicked event.
(WebInspector.DataGridNode.prototype.createGoToArrowButton.buttonClicked): Deleted.
(WebInspector.DataGridNode.prototype.createGoToArrowButton): Deleted.
Now part of TimelineDataGridNode.

* UserInterface/Views/LayoutTimelineDataGridNode.js:
(WebInspector.LayoutTimelineDataGridNode):
(WebInspector.LayoutTimelineDataGridNode.prototype.get data):
Add name cell to row data.
(WebInspector.LayoutTimelineDataGridNode.prototype.createCellContent):
Create name cell.

* UserInterface/Views/LayoutTimelineView.css:
(.timeline-view.layout > .data-grid .eventType-column): Deleted.
Column border no longer hidden.

* UserInterface/Views/LayoutTimelineView.js:
(WebInspector.LayoutTimelineView):
Setup name column.

* UserInterface/Views/NetworkTimelineView.css:
(.timeline-view.network > .data-grid .name-column .subtitle):
Don't show subtitles in the Network grid's name column.

* UserInterface/Views/NetworkTimelineView.js:
(WebInspector.NetworkTimelineView):
Setup name column.

* UserInterface/Views/OverviewTimelineView.css:
(.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler):
(.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler > .header):
(.timeline-view.overview > .data-grid th):
(body.window-inactive .timeline-view.overview > .data-grid th):
(.timeline-view.overview .timeline-ruler > .event-markers):
(.timeline-view.overview > .data-grid):
(.timeline-view.overview > .timeline-ruler): Deleted.
(.timeline-view.overview > .timeline-ruler > .header): Deleted.
(body.window-inactive .timeline-view.overview > .timeline-ruler > .header): Deleted.
(.timeline-view.overview > .timeline-ruler > .event-markers): Deleted.
New styles for adding grid column headers and using a TimelineRuler as the
graph column header.

* UserInterface/Views/OverviewTimelineView.js:
(WebInspector.OverviewTimelineView):
Setup name column and add ruler to graph column header.

* UserInterface/Views/ProfileNodeDataGridNode.js:
(WebInspector.ProfileNodeDataGridNode):
Use cached data instead of creating row data at construction time.
(WebInspector.ProfileNodeDataGridNode.prototype.get data):
Add name cell to row data.
(WebInspector.ProfileNodeDataGridNode.prototype.createCellContent):
Create name cell.
(WebInspector.ProfileNodeDataGridNode.prototype._iconClassNameForProfileNode):
(WebInspector.ProfileNodeDataGridNode.prototype._titleForProfileNode):
Copied from ProfileNodeTreeElement.

* UserInterface/Views/RenderingFrameTimelineDataGridNode.js:
(WebInspector.RenderingFrameTimelineDataGridNode):
(WebInspector.RenderingFrameTimelineDataGridNode.prototype.get data):
Add name cell to row data.
(WebInspector.RenderingFrameTimelineDataGridNode.prototype.createCellContent):
Create name cell.

* UserInterface/Views/RenderingFrameTimelineView.js:
(WebInspector.RenderingFrameTimelineView):
Setup name column.

* UserInterface/Views/ResourceTimelineDataGridNode.js:
(WebInspector.ResourceTimelineDataGridNode):
Renamed "graphOnly" to "includesGraph", since resource rows in the overview
now show the name column in addition to the graph column. Resource events
LoadingDidFinish and LoadingDidFail now need to be handled for both types
of resource rows.

(WebInspector.ResourceTimelineDataGridNode.prototype.get data):
(WebInspector.ResourceTimelineDataGridNode.prototype.createCellContent):
Update resource status element and create name cell content.
(WebInspector.ResourceTimelineDataGridNode.prototype._createNameCellDocumentFragment):
Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.
(WebInspector.ResourceTimelineDataGridNode.prototype._dataGridNodeGoToArrowClicked):
Show resource when goto arrow is clicked.
(WebInspector.ResourceTimelineDataGridNode.prototype._updateStatus):
Update name cell's text color and progress spinner.

* UserInterface/Views/ResourceTreeElement.css:
(.item.resource.failed):
(.item.resource.failed .subtitle):
Use --error-text-color CSS variable.

* UserInterface/Views/ScriptTimelineDataGridNode.js:
(WebInspector.ScriptTimelineDataGridNode):
(WebInspector.ScriptTimelineDataGridNode.prototype.createCellContent):
(WebInspector.ScriptTimelineDataGridNode.prototype._createNameCellDocumentFragment):
Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.

* UserInterface/Views/ScriptTimelineView.js:
(WebInspector.ScriptTimelineView):
Setup name column.

* UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js:
(WebInspector.SourceCodeTimelineTimelineDataGridNode.prototype.createCellContent):
Added now that this node type is no longer "graph only".
(WebInspector.SourceCodeTimelineTimelineDataGridNode.prototype._createNameCellContent):
Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.

* UserInterface/Views/TimelineDataGridNode.js:
(WebInspector.TimelineDataGridNode):
Renamed `graphOnly` to `includesGraph`.
(WebInspector.TimelineDataGridNode.prototype.createCellContent):
Removed icon element creation. This is now handled by the DataGrid.
(WebInspector.TimelineDataGridNode.prototype.refresh):
Refresh of all node cells after updating the graph.
(WebInspector.TimelineDataGridNode.prototype.createGoToArrowButton):
(WebInspector.TimelineDataGridNode.prototype.createGoToArrowButton.buttonClicked):
Relocated from DataGrid, as it's only used by TimelineDataGridNodes.

* UserInterface/Views/TimelineView.css:
(.timeline-view > .data-grid .indeterminate-progress-spinner):
Styles for grid cell progress spinners.

* UserInterface/Views/Variables.css:
(:root):
Added --error-text-color variable to remove duplication.

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

21 files changed:
Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Views/DataGrid.css
Source/WebInspectorUI/UserInterface/Views/DataGrid.js
Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.css
Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js
Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.css
Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js
Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.css
Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js
Source/WebInspectorUI/UserInterface/Views/ProfileNodeDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js
Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/ResourceTreeElement.css
Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/ScriptTimelineView.js
Source/WebInspectorUI/UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js
Source/WebInspectorUI/UserInterface/Views/TimelineView.css
Source/WebInspectorUI/UserInterface/Views/Variables.css

index 02fb7d9..a6eb8db 100644 (file)
@@ -1,5 +1,151 @@
 2016-03-02  Matt Baker  <mattbaker@apple.com>
 
+        Web Inspector: Timelines UI redesign: show content tree outline records in timeline data grids
+        https://bugs.webkit.org/show_bug.cgi?id=153032
+        <rdar://problem/24195317>
+
+        Reviewed by Timothy Hatcher.
+
+        This patch relocates the data shown in the Timelines navigation sidebar content tree outline
+        to a new grid column in each TimelineDataGrid. Logic for creating subtitles, goto arrow buttons,
+        and status elements (the progress spinner used for network resources) has been replicated in
+        the appropriate TimelineDataGridNode classes.
+
+        Duplicate logic contained in TimelineRecordTreeElement classes is left in place for now, but
+        will be removed in <https://webkit.org/b/153036>.
+
+        * UserInterface/Views/DataGrid.css:
+        (.data-grid td.error):
+        Use --error-text-color CSS variable.
+
+        * UserInterface/Views/DataGrid.js:
+        Removed GoToArrowClicked event.
+        (WebInspector.DataGridNode.prototype.createGoToArrowButton.buttonClicked): Deleted.
+        (WebInspector.DataGridNode.prototype.createGoToArrowButton): Deleted.
+        Now part of TimelineDataGridNode.
+
+        * UserInterface/Views/LayoutTimelineDataGridNode.js:
+        (WebInspector.LayoutTimelineDataGridNode):
+        (WebInspector.LayoutTimelineDataGridNode.prototype.get data):
+        Add name cell to row data.
+        (WebInspector.LayoutTimelineDataGridNode.prototype.createCellContent):
+        Create name cell.
+
+        * UserInterface/Views/LayoutTimelineView.css:
+        (.timeline-view.layout > .data-grid .eventType-column): Deleted.
+        Column border no longer hidden.
+
+        * UserInterface/Views/LayoutTimelineView.js:
+        (WebInspector.LayoutTimelineView):
+        Setup name column.
+
+        * UserInterface/Views/NetworkTimelineView.css:
+        (.timeline-view.network > .data-grid .name-column .subtitle):
+        Don't show subtitles in the Network grid's name column.
+
+        * UserInterface/Views/NetworkTimelineView.js:
+        (WebInspector.NetworkTimelineView):
+        Setup name column.
+
+        * UserInterface/Views/OverviewTimelineView.css:
+        (.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler):
+        (.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler > .header):
+        (.timeline-view.overview > .data-grid th):
+        (body.window-inactive .timeline-view.overview > .data-grid th):
+        (.timeline-view.overview .timeline-ruler > .event-markers):
+        (.timeline-view.overview > .data-grid):
+        (.timeline-view.overview > .timeline-ruler): Deleted.
+        (.timeline-view.overview > .timeline-ruler > .header): Deleted.
+        (body.window-inactive .timeline-view.overview > .timeline-ruler > .header): Deleted.
+        (.timeline-view.overview > .timeline-ruler > .event-markers): Deleted.
+        New styles for adding grid column headers and using a TimelineRuler as the
+        graph column header.
+
+        * UserInterface/Views/OverviewTimelineView.js:
+        (WebInspector.OverviewTimelineView):
+        Setup name column and add ruler to graph column header.
+
+        * UserInterface/Views/ProfileNodeDataGridNode.js:
+        (WebInspector.ProfileNodeDataGridNode):
+        Use cached data instead of creating row data at construction time.
+        (WebInspector.ProfileNodeDataGridNode.prototype.get data):
+        Add name cell to row data.
+        (WebInspector.ProfileNodeDataGridNode.prototype.createCellContent):
+        Create name cell.
+        (WebInspector.ProfileNodeDataGridNode.prototype._iconClassNameForProfileNode):
+        (WebInspector.ProfileNodeDataGridNode.prototype._titleForProfileNode):
+        Copied from ProfileNodeTreeElement.
+
+        * UserInterface/Views/RenderingFrameTimelineDataGridNode.js:
+        (WebInspector.RenderingFrameTimelineDataGridNode):
+        (WebInspector.RenderingFrameTimelineDataGridNode.prototype.get data):
+        Add name cell to row data.
+        (WebInspector.RenderingFrameTimelineDataGridNode.prototype.createCellContent):
+        Create name cell.
+
+        * UserInterface/Views/RenderingFrameTimelineView.js:
+        (WebInspector.RenderingFrameTimelineView):
+        Setup name column.
+
+        * UserInterface/Views/ResourceTimelineDataGridNode.js:
+        (WebInspector.ResourceTimelineDataGridNode):
+        Renamed "graphOnly" to "includesGraph", since resource rows in the overview
+        now show the name column in addition to the graph column. Resource events
+        LoadingDidFinish and LoadingDidFail now need to be handled for both types
+        of resource rows.
+
+        (WebInspector.ResourceTimelineDataGridNode.prototype.get data):
+        (WebInspector.ResourceTimelineDataGridNode.prototype.createCellContent):
+        Update resource status element and create name cell content.
+        (WebInspector.ResourceTimelineDataGridNode.prototype._createNameCellDocumentFragment):
+        Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.
+        (WebInspector.ResourceTimelineDataGridNode.prototype._dataGridNodeGoToArrowClicked):
+        Show resource when goto arrow is clicked.
+        (WebInspector.ResourceTimelineDataGridNode.prototype._updateStatus):
+        Update name cell's text color and progress spinner.
+
+        * UserInterface/Views/ResourceTreeElement.css:
+        (.item.resource.failed):
+        (.item.resource.failed .subtitle):
+        Use --error-text-color CSS variable.
+
+        * UserInterface/Views/ScriptTimelineDataGridNode.js:
+        (WebInspector.ScriptTimelineDataGridNode):
+        (WebInspector.ScriptTimelineDataGridNode.prototype.createCellContent):
+        (WebInspector.ScriptTimelineDataGridNode.prototype._createNameCellDocumentFragment):
+        Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.
+
+        * UserInterface/Views/ScriptTimelineView.js:
+        (WebInspector.ScriptTimelineView):
+        Setup name column.
+
+        * UserInterface/Views/SourceCodeTimelineTimelineDataGridNode.js:
+        (WebInspector.SourceCodeTimelineTimelineDataGridNode.prototype.createCellContent):
+        Added now that this node type is no longer "graph only".
+        (WebInspector.SourceCodeTimelineTimelineDataGridNode.prototype._createNameCellContent):
+        Create DOM fragment with titles. Based on code in TimelineRecordTreeElement.
+
+        * UserInterface/Views/TimelineDataGridNode.js:
+        (WebInspector.TimelineDataGridNode):
+        Renamed `graphOnly` to `includesGraph`.
+        (WebInspector.TimelineDataGridNode.prototype.createCellContent):
+        Removed icon element creation. This is now handled by the DataGrid.
+        (WebInspector.TimelineDataGridNode.prototype.refresh):
+        Refresh of all node cells after updating the graph.
+        (WebInspector.TimelineDataGridNode.prototype.createGoToArrowButton):
+        (WebInspector.TimelineDataGridNode.prototype.createGoToArrowButton.buttonClicked):
+        Relocated from DataGrid, as it's only used by TimelineDataGridNodes.
+
+        * UserInterface/Views/TimelineView.css:
+        (.timeline-view > .data-grid .indeterminate-progress-spinner):
+        Styles for grid cell progress spinners.
+
+        * UserInterface/Views/Variables.css:
+        (:root):
+        Added --error-text-color variable to remove duplication.
+
+2016-03-02  Matt Baker  <mattbaker@apple.com>
+
         Web Inspector: Timelines UI redesign: relocate recording controls to TimelineTabContentView's content browser
         https://bugs.webkit.org/show_bug.cgi?id=153532
         <rdar://problem/24361611>
index 8c34d33..9f3f4c9 100644 (file)
 }
 
 .data-grid td.error {
-    color: hsl(0, 86%, 47%);
+    color: var(--error-text-color);
 }
 
 .data-grid tr.selected td.error {
index ea4c627..41b28c4 100644 (file)
@@ -1397,8 +1397,7 @@ WebInspector.DataGrid.Event = {
     SortChanged: "datagrid-sort-changed",
     SelectedNodeChanged: "datagrid-selected-node-changed",
     ExpandedNode: "datagrid-expanded-node",
-    CollapsedNode: "datagrid-collapsed-node",
-    GoToArrowClicked: "datagrid-go-to-arrow-clicked"
+    CollapsedNode: "datagrid-collapsed-node"
 };
 
 WebInspector.DataGrid.ResizeMethod = {
@@ -1508,26 +1507,6 @@ WebInspector.DataGridNode = class DataGridNode extends WebInspector.Object
             this._element.appendChild(this.createCell(columnIdentifier));
     }
 
-    createGoToArrowButton(cellElement)
-    {
-        function buttonClicked(event)
-        {
-            if (this.hidden || !this.revealed)
-                return;
-
-            event.stopPropagation();
-
-            let columnIdentifier = cellElement.__columnIdentifier;
-            this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Event.GoToArrowClicked, {dataGridNode: this, columnIdentifier});
-        }
-
-        let button = WebInspector.createGoToArrowButton();
-        button.addEventListener("click", buttonClicked.bind(this));
-
-        let contentElement = cellElement.firstChild;
-        contentElement.appendChild(button);
-    }
-
     refreshIfNeeded()
     {
         if (!this._needsRefresh)
index 9f71d16..dffc203 100644 (file)
@@ -49,7 +49,7 @@ WebInspector.LayoutTimelineDataGridNode = class LayoutTimelineDataGridNode exten
     {
         if (!this._cachedData) {
             this._cachedData = {
-                eventType: this._record.eventType,
+                name: WebInspector.LayoutTimelineRecord.displayNameForEventType(this._record.eventType),
                 width: this._record.width,
                 height: this._record.height,
                 area: this._record.width * this._record.height,
@@ -67,8 +67,9 @@ WebInspector.LayoutTimelineDataGridNode = class LayoutTimelineDataGridNode exten
         var value = this.data[columnIdentifier];
 
         switch (columnIdentifier) {
-        case "eventType":
-            return WebInspector.LayoutTimelineRecord.displayNameForEventType(value);
+        case "name":
+            cell.classList.add(WebInspector.TimelineTabContentView.iconClassNameForRecord(this._record));
+            return value;
 
         case "width":
         case "height":
index 2830d3a..24cd72b 100644 (file)
     bottom: 0;
 }
 
-.timeline-view.layout > .data-grid .eventType-column {
-    border-right: none;
-}
-
 .sidebar > .panel.navigation.timeline.timeline-recording-content-view-showing .tree-outline.layout .item .subtitle {
     display: none;
 }
index bde64b7..5d2756e 100644 (file)
@@ -33,10 +33,10 @@ WebInspector.LayoutTimelineView = class LayoutTimelineView extends WebInspector.
 
         this.navigationSidebarTreeOutline.element.classList.add("layout");
 
-        var columns = {eventType: {}, location: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
+        let columns = {name: {}, location: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
 
-        columns.eventType.title = WebInspector.UIString("Type");
-        columns.eventType.width = "15%";
+        columns.name.title = WebInspector.UIString("Type");
+        columns.name.width = "15%";
 
         var typeToLabelMap = new Map;
         for (var key in WebInspector.LayoutTimelineRecord.EventType) {
@@ -44,9 +44,11 @@ WebInspector.LayoutTimelineView = class LayoutTimelineView extends WebInspector.
             typeToLabelMap.set(value, WebInspector.LayoutTimelineRecord.displayNameForEventType(value));
         }
 
-        columns.eventType.scopeBar = WebInspector.TimelineDataGrid.createColumnScopeBar("layout", typeToLabelMap);
-        columns.eventType.hidden = true;
-        this._scopeBar = columns.eventType.scopeBar;
+        columns.name.scopeBar = WebInspector.TimelineDataGrid.createColumnScopeBar("layout", typeToLabelMap);
+        columns.name.disclosure = true;
+        columns.name.icon = true;
+
+        this._scopeBar = columns.name.scopeBar;
 
         columns.location.title = WebInspector.UIString("Initiator");
         columns.location.width = "25%";
index 838f154..47092ff 100644 (file)
     bottom: 0;
 }
 
+.timeline-view.network > .data-grid .name-column .subtitle {
+    display: none;
+}
+
 .sidebar > .panel.navigation.timeline.timeline-recording-content-view-showing .tree-outline.network .item .subtitle {
     display: none;
 }
index 22bf91f..4daf827 100644 (file)
@@ -34,7 +34,11 @@ WebInspector.NetworkTimelineView = class NetworkTimelineView extends WebInspecto
         this.navigationSidebarTreeOutline.disclosureButtons = false;
         this.navigationSidebarTreeOutline.element.classList.add("network");
 
-        var columns = {domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}};
+        let columns = {name: {}, domain: {}, type: {}, method: {}, scheme: {}, statusCode: {}, cached: {}, size: {}, transferSize: {}, requestSent: {}, latency: {}, duration: {}};
+
+        columns.name.title = WebInspector.UIString("Name");
+        columns.name.icon = true;
+        columns.name.width = "10%";
 
         columns.domain.title = WebInspector.UIString("Domain");
         columns.domain.width = "10%";
index b75f79c..81c5feb 100644 (file)
  * THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-.timeline-view.overview > .timeline-ruler {
+.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler {
     position: absolute;
     top: 0;
-    left: 0;
-    right: 0;
     bottom: 0;
 }
 
-.timeline-view.overview > .timeline-ruler > .header {
-    border-top: 1px solid var(--border-color);
-    height: 23px;
+.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler > .header {
+    border: none;
+    height: 22px;
 }
 
-.timeline-view.overview > .timeline-ruler > .event-markers {
-    top: 23px;
-    border-top: 1px solid var(--border-color);
+.timeline-view.overview > .data-grid th.graph-column > .timeline-ruler > .event-markers {
+    top: 22px;
 }
 
 .timeline-view.overview > .data-grid {
     position: absolute;
-    top: 23px;
+    top: 0;
     left: 0;
     right: 0;
     bottom: 0;
 }
 
+.timeline-view.overview > .data-grid th {
+    border-top: solid 1px var(--border-color);
+}
+
 .timeline-view.overview > .data-grid td.graph-column {
     padding: 2px 0;
 }
index 1e23338..e6a12bc 100644 (file)
@@ -31,18 +31,24 @@ WebInspector.OverviewTimelineView = class OverviewTimelineView extends WebInspec
 
         this._recording = recording;
 
-        var columns = {"graph": {width: "100%"}};
+        let columns = {name: {}, graph: {}};
+
+        columns.name.title = WebInspector.UIString("Name");
+        columns.name.width = "20%";
+        columns.name.icon = true;
+        columns.name.disclosure = true;
+
+        this._timelineRuler = new WebInspector.TimelineRuler;
+        this._timelineRuler.allowsClippedLabels = true;
+
+        columns.graph.width = "80%";
+        columns.graph.headerView = this._timelineRuler;
 
         this._dataGrid = new WebInspector.DataGrid(columns);
         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
-        this._dataGrid.element.classList.add("no-header");
 
         this._treeOutlineDataGridSynchronizer = new WebInspector.TreeOutlineDataGridSynchronizer(this.navigationSidebarTreeOutline, this._dataGrid);
 
-        this._timelineRuler = new WebInspector.TimelineRuler;
-        this._timelineRuler.allowsClippedLabels = true;
-        this.addSubview(this._timelineRuler);
-
         this._currentTimeMarker = new WebInspector.TimelineMarker(0, WebInspector.TimelineMarker.Type.CurrentTime);
         this._timelineRuler.addMarker(this._currentTimeMarker);
 
index d584c7d..711b1f5 100644 (file)
@@ -36,8 +36,7 @@ WebInspector.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends Web
         this._rangeStartTime = rangeStartTime || 0;
         this._rangeEndTime = typeof rangeEndTime === "number" ? rangeEndTime : Infinity;
 
-        this._data = this._profileNode.computeCallInfoForTimeRange(this._rangeStartTime, this._rangeEndTime);
-        this._data.location = this._profileNode.sourceCodeLocation;
+        this._cachedData = null;
     }
 
     // Public
@@ -69,7 +68,13 @@ WebInspector.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends Web
 
     get data()
     {
-        return this._data;
+        if (!this._cachedData) {
+            this._cachedData = this._profileNode.computeCallInfoForTimeRange(this._rangeStartTime, this._rangeEndTime);
+            this._cachedData.name = this._titleForProfileNode();
+            this._cachedData.location = this._profileNode.sourceCodeLocation;
+        }
+
+        return this._cachedData;
     }
 
     updateRangeTimes(startTime, endTime)
@@ -108,6 +113,10 @@ WebInspector.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends Web
         var value = this.data[columnIdentifier];
 
         switch (columnIdentifier) {
+        case "name":
+            cell.classList.add(this._iconClassNameForProfileNode());
+            return value;
+
         case "startTime":
             return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
 
@@ -119,4 +128,50 @@ WebInspector.ProfileNodeDataGridNode = class ProfileNodeDataGridNode extends Web
 
         return super.createCellContent(columnIdentifier, cell);
     }
+
+    // Private
+
+    _iconClassNameForProfileNode()
+    {
+        let className;
+        switch (this._profileNode.type) {
+        case WebInspector.ProfileNode.Type.Function:
+            className = WebInspector.CallFrameView.FunctionIconStyleClassName;
+            if (!this._profileNode.sourceCodeLocation)
+                className = WebInspector.CallFrameView.NativeIconStyleClassName;
+            break;
+        case WebInspector.ProfileNode.Type.Program:
+            className = WebInspector.TimelineRecordTreeElement.EvaluatedRecordIconStyleClass;
+            break;
+        }
+
+        console.assert(className);
+
+        // This is more than likely an event listener function with an "on" prefix and it is
+        // as long or longer than the shortest event listener name -- "oncut".
+        if (this._profileNode.functionName && this._profileNode.functionName.startsWith("on") && this._profileNode.functionName.length >= 5)
+            className = WebInspector.CallFrameView.EventListenerIconStyleClassName;
+
+        return className;
+    }
+
+    _titleForProfileNode()
+    {
+        let title = this._profileNode.functionName;
+        if (!name) {
+            switch (this._profileNode.type) {
+            case WebInspector.ProfileNode.Type.Function:
+                title = WebInspector.UIString("(anonymous function)");
+                break;
+            case WebInspector.ProfileNode.Type.Program:
+                title = WebInspector.UIString("(program)");
+                break;
+            default:
+                title = WebInspector.UIString("(anonymous function)");
+                console.error("Unknown ProfileNode type: " + this._profileNode.type);
+            }
+        }
+
+        return title;
+    }
 };
index 15e178f..26c8ac8 100644 (file)
@@ -48,11 +48,13 @@ WebInspector.RenderingFrameTimelineDataGridNode = class RenderingFrameTimelineDa
     get data()
     {
         if (!this._cachedData) {
-            var scriptTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Script);
-            var layoutTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Layout);
-            var paintTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Paint);
-            var otherTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Other);
+            let name = WebInspector.TimelineTabContentView.displayNameForRecord(this._record);
+            let scriptTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Script);
+            let layoutTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Layout);
+            let paintTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Paint);
+            let otherTime = this._record.durationForTask(WebInspector.RenderingFrameTimelineRecord.TaskType.Other);
             this._cachedData = {
+                name,
                 startTime: this._record.startTime,
                 totalTime: this._record.duration,
                 scriptTime,
@@ -70,6 +72,10 @@ WebInspector.RenderingFrameTimelineDataGridNode = class RenderingFrameTimelineDa
         var value = this.data[columnIdentifier];
 
         switch (columnIdentifier) {
+        case "name":
+            cell.classList.add(WebInspector.TimelineTabContentView.iconClassNameForRecord(this._record));
+            return value;
+
         case "startTime":
             return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
 
index b0c7b19..730cacf 100644 (file)
@@ -42,7 +42,12 @@ WebInspector.RenderingFrameTimelineView = class RenderingFrameTimelineView exten
         this._scopeBar = new WebInspector.ScopeBar("rendering-frame-scope-bar", scopeBarItems, scopeBarItems[0], true);
         this._scopeBar.addEventListener(WebInspector.ScopeBar.Event.SelectionChanged, this._scopeBarSelectionDidChange, this);
 
-        let columns = {totalTime: {}, scriptTime: {}, layoutTime: {}, paintTime: {}, otherTime: {}, startTime: {}, location: {}};
+        let columns = {name: {}, totalTime: {}, scriptTime: {}, layoutTime: {}, paintTime: {}, otherTime: {}, startTime: {}, location: {}};
+
+        columns.name.title = WebInspector.UIString("Name");
+        columns.name.width = "20%";
+        columns.name.icon = true;
+        columns.name.disclosure = true;
 
         columns.totalTime.title = WebInspector.UIString("Total Time");
         columns.totalTime.width = "15%";
index 0c6df8c..b6c62a3 100644 (file)
 
 WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode extends WebInspector.TimelineDataGridNode
 {
-    constructor(resourceTimelineRecord, graphOnly, graphDataSource)
+    constructor(resourceTimelineRecord, includesGraph, graphDataSource)
     {
-        super(graphOnly, graphDataSource);
+        super(includesGraph, graphDataSource);
 
         this._resource = resourceTimelineRecord.resource;
         this._record = resourceTimelineRecord;
 
-        this._record.addEventListener(WebInspector.TimelineRecord.Event.Updated, graphOnly ? this._timelineRecordUpdated : this._needsRefresh, this);
+        this._resource.addEventListener(WebInspector.Resource.Event.LoadingDidFinish, this._needsRefresh, this);
+        this._resource.addEventListener(WebInspector.Resource.Event.LoadingDidFail, this._needsRefresh, this);
+        this._resource.addEventListener(WebInspector.Resource.Event.URLDidChange, this._needsRefresh, this);
 
-        if (!graphOnly) {
-            this._resource.addEventListener(WebInspector.Resource.Event.URLDidChange, this._needsRefresh, this);
+        if (includesGraph)
+            this._record.addEventListener(WebInspector.TimelineRecord.Event.Updated, this._timelineRecordUpdated, this);
+        else {
             this._resource.addEventListener(WebInspector.Resource.Event.TypeDidChange, this._needsRefresh, this);
-            this._resource.addEventListener(WebInspector.Resource.Event.LoadingDidFinish, this._needsRefresh, this);
-            this._resource.addEventListener(WebInspector.Resource.Event.LoadingDidFail, this._needsRefresh, this);
             this._resource.addEventListener(WebInspector.Resource.Event.SizeDidChange, this._needsRefresh, this);
             this._resource.addEventListener(WebInspector.Resource.Event.TransferSizeDidChange, this._needsRefresh, this);
         }
@@ -64,7 +65,7 @@ WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode e
         var resource = this._resource;
         var data = {};
 
-        if (!this._graphOnly) {
+        if (!this._includesGraph) {
             var zeroTime = this.graphDataSource ? this.graphDataSource.zeroTime : 0;
 
             data.domain = WebInspector.displayNameForHost(resource.urlComponents.host);
@@ -96,6 +97,12 @@ WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode e
         var value = this.data[columnIdentifier];
 
         switch (columnIdentifier) {
+        case "name":
+            cell.classList.add(WebInspector.ResourceTreeElement.ResourceIconStyleClassName, resource.type);
+            cell.title = resource.displayURL;
+            this._updateStatus(cell);
+            return this._createNameCellDocumentFragment();
+
         case "type":
             return WebInspector.Resource.displayNameForType(value);
 
@@ -136,6 +143,37 @@ WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode e
 
     // Private
 
+    _createNameCellDocumentFragment()
+    {
+        let fragment = document.createDocumentFragment();
+        let mainTitle = WebInspector.TimelineTabContentView.displayNameForRecord(this._record);
+        fragment.append(mainTitle);
+
+        // Show the host as the subtitle if it is different from the main resource or if this is the main frame's main resource.
+        let frame = this._resource.parentFrame;
+        let isMainResource = this._resource.isMainResource();
+        let parentResourceHost;
+        if (frame && isMainResource) {
+            // When the resource is a main resource, get the host from the current frame's parent frame instead of the current frame.
+            parentResourceHost = frame.parentFrame ? frame.parentFrame.mainResource.urlComponents.host : null;
+        } else if (frame) {
+            // When the resource is a normal sub-resource, get the host from the current frame's main resource.
+            parentResourceHost = frame.mainResource.urlComponents.host;
+        }
+
+        if (parentResourceHost !== this._resource.urlComponents.host || frame.isMainFrame() && isMainResource) {
+            let subtitle = WebInspector.displayNameForHost(this._resource.urlComponents.host);
+            if (mainTitle !== subtitle) {
+                let subtitleElement = document.createElement("span");
+                subtitleElement.classList.add("subtitle");
+                subtitleElement.textContent = subtitle;
+                fragment.append(subtitleElement);
+            }
+        }
+
+        return fragment;
+    }
+
     _needsRefresh()
     {
         if (this.dataGrid instanceof WebInspector.TimelineDataGrid) {
@@ -154,4 +192,33 @@ WebInspector.ResourceTimelineDataGridNode = class ResourceTimelineDataGridNode e
         if (this.isRecordVisible(this._record))
             this.needsGraphRefresh();
     }
+
+    _dataGridNodeGoToArrowClicked()
+    {
+        WebInspector.showSourceCode(this._resource);
+    }
+
+    _updateStatus(cell)
+    {
+        if (this._resource.failed)
+            cell.classList.add("error");
+        else {
+            cell.classList.remove("error");
+
+            if (this._resource.finished)
+                this.createGoToArrowButton(cell, this._dataGridNodeGoToArrowClicked.bind(this));
+        }
+
+        if (this._spinner)
+            this._spinner.element.remove();
+
+        if (this._resource.finished || this._resource.failed)
+            return;
+
+        if (!this._spinner)
+            this._spinner = new WebInspector.IndeterminateProgressSpinner;
+
+        let contentElement = cell.firstChild;
+        contentElement.appendChild(this._spinner.element);
+    }
 };
index f89b877..90a5b3e 100644 (file)
  */
 
 .item.resource.failed {
-    color: hsl(0, 86%, 47%) !important;
+    color: var(--error-text-color) !important;
 }
 
 .item.resource.failed .subtitle {
-    color: hsla(0, 86%, 47%, 0.7) !important;
+    color: var(--error-text-color) !important;
+    opacity: 0.7;
 }
index 2121b7a..9130504 100644 (file)
@@ -124,8 +124,9 @@ WebInspector.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode exten
         var value = this.data[columnIdentifier];
 
         switch (columnIdentifier) {
-        case "eventType":
-            return WebInspector.ScriptTimelineRecord.EventType.displayName(value, this._record.details);
+        case "name":
+            cell.classList.add(WebInspector.TimelineTabContentView.iconClassNameForRecord(this._record));
+            return this._createNameCellDocumentFragment();
 
         case "startTime":
             return isNaN(value) ? emDash : Number.secondsToString(value - this._baseStartTime, true);
@@ -141,4 +142,27 @@ WebInspector.ScriptTimelineDataGridNode = class ScriptTimelineDataGridNode exten
 
         return super.createCellContent(columnIdentifier, cell);
     }
+
+    // Private
+
+    _createNameCellDocumentFragment(cellElement)
+    {
+        let fragment = document.createDocumentFragment();
+        let mainTitle = WebInspector.TimelineTabContentView.displayNameForRecord(this._record);
+        fragment.append(mainTitle);
+
+        if (this._record.eventType === WebInspector.ScriptTimelineRecord.EventType.TimerInstalled) {
+            let subtitleElement = document.createElement("span");
+            subtitleElement.classList.add("subtitle");
+            fragment.append(subtitleElement);
+
+            let timeoutString = Number.secondsToString(this._record.details.timeout / 1000);
+            if (this._record.details.repeating)
+                subtitleElement.textContent = WebInspector.UIString("%s interval").format(timeoutString);
+            else
+                subtitleElement.textContent = WebInspector.UIString("%s delay").format(timeoutString);
+        }
+
+        return fragment;
+    }
 };
index c8e7e5e..fc7ef45 100644 (file)
@@ -33,9 +33,15 @@ WebInspector.ScriptTimelineView = class ScriptTimelineView extends WebInspector.
 
         this.navigationSidebarTreeOutline.element.classList.add("script");
 
-        var columns = {location: {}, callCount: {}, startTime: {}, totalTime: {}, selfTime: {}, averageTime: {}};
+        let columns = {name: {}, location: {}, callCount: {}, startTime: {}, totalTime: {}, selfTime: {}, averageTime: {}};
+
+        columns.name.title = WebInspector.UIString("Name");
+        columns.name.width = "10%";
+        columns.name.icon = true;
+        columns.name.disclosure = true;
 
         columns.location.title = WebInspector.UIString("Location");
+        columns.location.icon = true;
         columns.location.width = "15%";
 
         let isSamplingProfiler = !!window.ScriptProfilerAgent;
index 6982d3c..b45de34 100644 (file)
@@ -50,8 +50,44 @@ WebInspector.SourceCodeTimelineTimelineDataGridNode = class SourceCodeTimelineTi
         return {graph: this._sourceCodeTimeline.startTime};
     }
 
+    createCellContent(columnIdentifier, cell)
+    {
+        if (columnIdentifier === "name" && this.records.length) {
+            cell.classList.add(WebInspector.TimelineTabContentView.iconClassNameForRecord(this.records[0]));
+            return this._createNameCellContent(cell);
+        }
+
+        return super.createCellContent(columnIdentifier, cell);
+    }
+
     // Private
 
+    _createNameCellContent(cellElement)
+    {
+        if (!this.records.length)
+            return null;
+
+        let fragment = document.createDocumentFragment();
+        let mainTitle = WebInspector.TimelineTabContentView.displayNameForRecord(this.records[0]);
+        fragment.append(mainTitle);
+
+        let sourceCodeLocation = this._sourceCodeTimeline.sourceCodeLocation;
+        if (sourceCodeLocation) {
+            let subtitleElement = document.createElement("span");
+            subtitleElement.classList.add("subtitle");
+            sourceCodeLocation.populateLiveDisplayLocationString(subtitleElement, "textContent", null, WebInspector.SourceCodeLocation.NameStyle.None, WebInspector.UIString("line "));
+
+            let goToArrowButtonLink = WebInspector.createSourceCodeLocationLink(sourceCodeLocation, false, true);
+            fragment.append(goToArrowButtonLink, subtitleElement);
+
+            // Give the whole cell a tooltip and keep it up to date.
+            sourceCodeLocation.populateLiveDisplayLocationTooltip(cellElement, mainTitle + "\n");
+        } else
+            cellElement.title = mainTitle;
+
+        return fragment;
+    }
+
     _timelineRecordAdded(event)
     {
         if (this.isRecordVisible(event.data.record))
index f820220..4956a10 100644 (file)
 
 WebInspector.TimelineDataGridNode = class TimelineDataGridNode extends WebInspector.DataGridNode
 {
-    constructor(graphOnly, graphDataSource, hasChildren)
+    constructor(includesGraph, graphDataSource, hasChildren)
     {
         super({}, hasChildren);
 
         this.copyable = false;
 
-        this._graphOnly = graphOnly || false;
+        this._includesGraph = includesGraph || false;
         this._graphDataSource = graphDataSource || null;
 
         if (graphDataSource) {
@@ -124,10 +124,6 @@ WebInspector.TimelineDataGridNode = class TimelineDataGridNode extends WebInspec
             var goToArrowButtonLink = WebInspector.createSourceCodeLocationLink(value, false, true);
             fragment.appendChild(goToArrowButtonLink);
 
-            var icon = document.createElement("div");
-            icon.className = "icon";
-            fragment.appendChild(icon);
-
             var titleElement = document.createElement("span");
             value.populateLiveDisplayLocationString(titleElement, "textContent");
             fragment.appendChild(titleElement);
@@ -156,10 +152,6 @@ WebInspector.TimelineDataGridNode = class TimelineDataGridNode extends WebInspec
                 var goToArrowButtonLink = WebInspector.createSourceCodeLocationLink(callFrame.sourceCodeLocation, false, true);
                 fragment.appendChild(goToArrowButtonLink);
 
-                var icon = document.createElement("div");
-                icon.classList.add("icon");
-                fragment.appendChild(icon);
-
                 if (isAnonymousFunction) {
                     // For anonymous functions we show the resource or script icon and name.
                     if (callFrame.sourceCodeLocation.sourceCode instanceof WebInspector.Resource) {
@@ -207,10 +199,8 @@ WebInspector.TimelineDataGridNode = class TimelineDataGridNode extends WebInspec
 
     refresh()
     {
-        if (this._graphDataSource && this._graphOnly) {
+        if (this._graphDataSource && this._includesGraph)
             this.needsGraphRefresh();
-            return;
-        }
 
         super.refresh();
     }
@@ -320,6 +310,25 @@ WebInspector.TimelineDataGridNode = class TimelineDataGridNode extends WebInspec
 
     // Protected
 
+    createGoToArrowButton(cellElement, callback)
+    {
+        function buttonClicked(event)
+        {
+            if (this.hidden || !this.revealed)
+                return;
+
+            event.stopPropagation();
+
+            callback(this, cellElement.__columnIdentifier);
+        }
+
+        let button = WebInspector.createGoToArrowButton();
+        button.addEventListener("click", buttonClicked.bind(this));
+
+        let contentElement = cellElement.firstChild;
+        contentElement.appendChild(button);
+    }
+
     isRecordVisible(record)
     {
         if (!this._graphDataSource)
index 7f62a82..f7a3d4b 100644 (file)
     bottom: 0;
 }
 
+.timeline-view > .data-grid .indeterminate-progress-spinner {
+    float: right;
+    margin-left: 2px;
+}
+
 .panel.navigation.timeline > .content > .tree-outline {
     min-height: 100%;
     background-image: none;
index 01abae0..9f81511 100644 (file)
@@ -49,6 +49,8 @@
     --console-secondary-text-color: hsla(0, 0%, 0%, 0.33);
     --console-prompt-min-height: 30px;
 
+    --error-text-color: hsl(0, 86%, 47%);
+
     --syntax-highlight-number-color: hsl(248, 100%, 40%);
     --syntax-highlight-boolean-color: hsl(309, 85%, 35%);
     --syntax-highlight-string-color: hsl(1, 79%, 42%);