Title: [222868] trunk/Source/WebInspectorUI
Revision
222868
Author
[email protected]
Date
2017-10-04 12:17:30 -0700 (Wed, 04 Oct 2017)

Log Message

Web Inspector: Detail Views for resources in Network Tab
https://bugs.webkit.org/show_bug.cgi?id=177553

Reviewed by Devin Rousso.

* Localizations/en.lproj/localizedStrings.js:
* UserInterface/Main.html:
New strings and resources.

* UserInterface/Base/Main.js:
(WI._focusedContentBrowser):
Detect nested content browsers instead of only top level tab content browsers.

* UserInterface/Base/Setting.js:
Add a new global setting for which Network Detail view is preferred.

* UserInterface/Views/ContentBrowser.css:
(.content-browser > .navigation-bar .item):
(.content-browser > .navigation-bar > .item): Deleted.
Generalize a navigation item style so it works on items nested inside a group.

* UserInterface/Views/ContentBrowser.js:
(WI.ContentBrowser.prototype._updateContentViewSelectionPathNavigationItem):
(WI.ContentBrowser.prototype._updateContentViewNavigationItems):
(WI.ContentBrowser.prototype._removeAllNavigationItems):
Give ContentBrowser a way to group all ContentView specific navigation items
inside a GroupNavigationItem. This lets the client decide what to do with
those navigation items, instead of default behavior in the navigation bar.

* UserInterface/Views/ContentViewContainer.js:
(WI.ContentViewContainer.prototype.showContentView):
Avoid a flash when showContentView is called with the current content view.

* UserInterface/Views/FlexibleSpaceNavigationItem.css:
(:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item):
(:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item):
When containing a navigation item decide where you want the items to align to.

* UserInterface/Views/FlexibleSpaceNavigationItem.js:
(WI.FlexibleSpaceNavigationItem):
(WI.FlexibleSpaceNavigationItem.prototype.updateLayout):
Provide an option to embed a NavigationItem within a FlexibleSpace. Its behavior right
now is rather simple. If the embedded Item fits in the current available space it is
shown. If it doesn't fit, it is hidden and we have just a flexible space. This is used
in the network detail view's navigation bar to keep the main navigation items centered
while allowing for buttons to show up on the side without affecting the centering.

* UserInterface/Views/NavigationBar.js:
(WI.NavigationBar):
(WI.NavigationBar.prototype._mouseDown):
(WI.NavigationBar.prototype._mouseUp):
Simplify event registration. This would also help avoid cases where we
might have registered multiple mousedown handlers.

* UserInterface/Views/GroupNavigationItem.js:
(WI.GroupNavigationItem):
(WI.GroupNavigationItem.prototype.get navigationItems):
(WI.GroupNavigationItem.prototype.set navigationItems):
(WI.GroupNavigationItem.prototype.get width):
(WI.GroupNavigationItem.prototype.get minimumWidth):
(WI.GroupNavigationItem.prototype._updateItems):
* UserInterface/Views/HierarchicalPathNavigationItem.js:
(WI.HierarchicalPathNavigationItem):
(WI.HierarchicalPathNavigationItem.prototype.set components):
(WI.HierarchicalPathNavigationItem.prototype.updateLayout):
(WI.HierarchicalPathNavigationItem.prototype._updateComponentsIfNeeded):
Defer DOM modifications until layout for NavigationItems container classes
that change items/components dynamically. This reduces UI flashing in the
bar when items/components change by coalescing all DOM updates at the same
time; when the NavigationBar does its next layout.

* UserInterface/Views/NetworkResourceDetailView.css:
(.network-resource-detail):
(.network-resource-detail .navigation-bar):
(.network-resource-detail .item.close > .glyph):
(.network-resource-detail .item.close > .glyph:hover):
(.network-resource-detail .item.close > .glyph:active):
(.network .network-resource-detail .navigation-bar .item.radio.button.text-only):
(.network .network-resource-detail .navigation-bar .item.radio.button.text-only.selected):
(.network-resource-detail > .content-browser):
Styles for the detail view's navigation bar.

* UserInterface/Views/NetworkResourceDetailView.js: Added.
(WI.NetworkResourceDetailView):
(WI.NetworkResourceDetailView.prototype.get resource):
(WI.NetworkResourceDetailView.prototype.shown):
(WI.NetworkResourceDetailView.prototype.hidden):
(WI.NetworkResourceDetailView.prototype.dispose):
(WI.NetworkResourceDetailView.prototype.initialLayout):
(WI.NetworkResourceDetailView.prototype._showPreferredContentView):
(WI.NetworkResourceDetailView.prototype._showContentViewForNavigationItem):
(WI.NetworkResourceDetailView.prototype._navigationItemSelected):
(WI.NetworkResourceDetailView.prototype._handleCloseButton):
ContentBrowser with customized navigation bar. This container has a fixed
list of ContentViews all relating to the Resource. The detail view has
a single delegate method for its close button. Since it maintains a
ContentBrowser it needs to expose shown/hidden/dispose logic to ensure
proper ContentView lifecycle events.

* UserInterface/Views/NetworkTableContentView.css:
(.showing-detail .table .cell:not(.name)):
(.showing-detail .table .resizer:not(:first-of-type)):
* UserInterface/Views/NetworkTableContentView.js:
(WI.NetworkTableContentView):
(WI.NetworkTableContentView.prototype.shown):
(WI.NetworkTableContentView.prototype.hidden):
(WI.NetworkTableContentView.prototype.closed):
(WI.NetworkTableContentView.prototype.reset):
(WI.NetworkTableContentView.prototype.networkResourceDetailViewClose):
(WI.NetworkTableContentView.prototype.tableSortChanged):
(WI.NetworkTableContentView.prototype.tableCellClicked):
(WI.NetworkTableContentView.prototype.tableSelectedRowChanged):
(WI.NetworkTableContentView.prototype.layout):
(WI.NetworkTableContentView.prototype._hideResourceDetailView):
(WI.NetworkTableContentView.prototype._showResourceDetailView):
(WI.NetworkTableContentView.prototype._positionDetailView):
(WI.NetworkTableContentView.prototype._updateFilteredEntries):
(WI.NetworkTableContentView.prototype._typeFilterScopeBarSelectionChanged):
(WI.NetworkTableContentView.prototype._restoreSelectedRow):
(WI.NetworkTableContentView.prototype._tableNameColumnDidChangeWidth):
Behavior for selecting a row and showing / hiding the detail view.
The detail view is positioned beside the Network Table's "name" column
and resizes when that column resizes.

* UserInterface/Views/Resizer.css:
(.resizer):
* UserInterface/Views/Table.css:
(.table > .resizers):
* UserInterface/Views/Table.js:
(WI.Table):
(WI.Table.prototype.get scrollContainer):
(WI.Table.prototype._positionResizerElements):
To let clients customize the table a bit, put resizers into their own
container and expose the scroll container.

* UserInterface/Views/Variables.css:
(:root):
Add a new button hover color, slightly lighter than the existing button active color.

Modified Paths

Added Paths

Diff

Modified: trunk/Source/WebInspectorUI/ChangeLog (222867 => 222868)


--- trunk/Source/WebInspectorUI/ChangeLog	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/ChangeLog	2017-10-04 19:17:30 UTC (rev 222868)
@@ -1,5 +1,146 @@
 2017-10-04  Joseph Pecoraro  <[email protected]>
 
+        Web Inspector: Detail Views for resources in Network Tab
+        https://bugs.webkit.org/show_bug.cgi?id=177553
+
+        Reviewed by Devin Rousso.
+
+        * Localizations/en.lproj/localizedStrings.js:
+        * UserInterface/Main.html:
+        New strings and resources.
+
+        * UserInterface/Base/Main.js:
+        (WI._focusedContentBrowser):
+        Detect nested content browsers instead of only top level tab content browsers.
+
+        * UserInterface/Base/Setting.js:
+        Add a new global setting for which Network Detail view is preferred.
+
+        * UserInterface/Views/ContentBrowser.css:
+        (.content-browser > .navigation-bar .item):
+        (.content-browser > .navigation-bar > .item): Deleted.
+        Generalize a navigation item style so it works on items nested inside a group.
+
+        * UserInterface/Views/ContentBrowser.js:
+        (WI.ContentBrowser.prototype._updateContentViewSelectionPathNavigationItem):
+        (WI.ContentBrowser.prototype._updateContentViewNavigationItems):
+        (WI.ContentBrowser.prototype._removeAllNavigationItems):
+        Give ContentBrowser a way to group all ContentView specific navigation items
+        inside a GroupNavigationItem. This lets the client decide what to do with
+        those navigation items, instead of default behavior in the navigation bar.
+
+        * UserInterface/Views/ContentViewContainer.js:
+        (WI.ContentViewContainer.prototype.showContentView):
+        Avoid a flash when showContentView is called with the current content view.
+
+        * UserInterface/Views/FlexibleSpaceNavigationItem.css:
+        (:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item):
+        (:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item):
+        When containing a navigation item decide where you want the items to align to.
+
+        * UserInterface/Views/FlexibleSpaceNavigationItem.js:
+        (WI.FlexibleSpaceNavigationItem):
+        (WI.FlexibleSpaceNavigationItem.prototype.updateLayout):
+        Provide an option to embed a NavigationItem within a FlexibleSpace. Its behavior right
+        now is rather simple. If the embedded Item fits in the current available space it is
+        shown. If it doesn't fit, it is hidden and we have just a flexible space. This is used
+        in the network detail view's navigation bar to keep the main navigation items centered
+        while allowing for buttons to show up on the side without affecting the centering.
+
+        * UserInterface/Views/NavigationBar.js:
+        (WI.NavigationBar):
+        (WI.NavigationBar.prototype._mouseDown):
+        (WI.NavigationBar.prototype._mouseUp):
+        Simplify event registration. This would also help avoid cases where we
+        might have registered multiple mousedown handlers.
+
+        * UserInterface/Views/GroupNavigationItem.js:
+        (WI.GroupNavigationItem):
+        (WI.GroupNavigationItem.prototype.get navigationItems):
+        (WI.GroupNavigationItem.prototype.set navigationItems):
+        (WI.GroupNavigationItem.prototype.get width):
+        (WI.GroupNavigationItem.prototype.get minimumWidth):
+        (WI.GroupNavigationItem.prototype._updateItems):
+        * UserInterface/Views/HierarchicalPathNavigationItem.js:
+        (WI.HierarchicalPathNavigationItem):
+        (WI.HierarchicalPathNavigationItem.prototype.set components):
+        (WI.HierarchicalPathNavigationItem.prototype.updateLayout):
+        (WI.HierarchicalPathNavigationItem.prototype._updateComponentsIfNeeded):
+        Defer DOM modifications until layout for NavigationItems container classes
+        that change items/components dynamically. This reduces UI flashing in the
+        bar when items/components change by coalescing all DOM updates at the same
+        time; when the NavigationBar does its next layout.
+
+        * UserInterface/Views/NetworkResourceDetailView.css:
+        (.network-resource-detail):
+        (.network-resource-detail .navigation-bar):
+        (.network-resource-detail .item.close > .glyph):
+        (.network-resource-detail .item.close > .glyph:hover):
+        (.network-resource-detail .item.close > .glyph:active):
+        (.network .network-resource-detail .navigation-bar .item.radio.button.text-only):
+        (.network .network-resource-detail .navigation-bar .item.radio.button.text-only.selected):
+        (.network-resource-detail > .content-browser):
+        Styles for the detail view's navigation bar.
+
+        * UserInterface/Views/NetworkResourceDetailView.js: Added.
+        (WI.NetworkResourceDetailView):
+        (WI.NetworkResourceDetailView.prototype.get resource):
+        (WI.NetworkResourceDetailView.prototype.shown):
+        (WI.NetworkResourceDetailView.prototype.hidden):
+        (WI.NetworkResourceDetailView.prototype.dispose):
+        (WI.NetworkResourceDetailView.prototype.initialLayout):
+        (WI.NetworkResourceDetailView.prototype._showPreferredContentView):
+        (WI.NetworkResourceDetailView.prototype._showContentViewForNavigationItem):
+        (WI.NetworkResourceDetailView.prototype._navigationItemSelected):
+        (WI.NetworkResourceDetailView.prototype._handleCloseButton):
+        ContentBrowser with customized navigation bar. This container has a fixed
+        list of ContentViews all relating to the Resource. The detail view has
+        a single delegate method for its close button. Since it maintains a
+        ContentBrowser it needs to expose shown/hidden/dispose logic to ensure
+        proper ContentView lifecycle events.
+
+        * UserInterface/Views/NetworkTableContentView.css:
+        (.showing-detail .table .cell:not(.name)):
+        (.showing-detail .table .resizer:not(:first-of-type)):
+        * UserInterface/Views/NetworkTableContentView.js:
+        (WI.NetworkTableContentView):
+        (WI.NetworkTableContentView.prototype.shown):
+        (WI.NetworkTableContentView.prototype.hidden):
+        (WI.NetworkTableContentView.prototype.closed):
+        (WI.NetworkTableContentView.prototype.reset):
+        (WI.NetworkTableContentView.prototype.networkResourceDetailViewClose):
+        (WI.NetworkTableContentView.prototype.tableSortChanged):
+        (WI.NetworkTableContentView.prototype.tableCellClicked):
+        (WI.NetworkTableContentView.prototype.tableSelectedRowChanged):
+        (WI.NetworkTableContentView.prototype.layout):
+        (WI.NetworkTableContentView.prototype._hideResourceDetailView):
+        (WI.NetworkTableContentView.prototype._showResourceDetailView):
+        (WI.NetworkTableContentView.prototype._positionDetailView):
+        (WI.NetworkTableContentView.prototype._updateFilteredEntries):
+        (WI.NetworkTableContentView.prototype._typeFilterScopeBarSelectionChanged):
+        (WI.NetworkTableContentView.prototype._restoreSelectedRow):
+        (WI.NetworkTableContentView.prototype._tableNameColumnDidChangeWidth):
+        Behavior for selecting a row and showing / hiding the detail view.
+        The detail view is positioned beside the Network Table's "name" column
+        and resizes when that column resizes.
+
+        * UserInterface/Views/Resizer.css:
+        (.resizer):
+        * UserInterface/Views/Table.css:
+        (.table > .resizers):
+        * UserInterface/Views/Table.js:
+        (WI.Table):
+        (WI.Table.prototype.get scrollContainer):
+        (WI.Table.prototype._positionResizerElements):
+        To let clients customize the table a bit, put resizers into their own
+        container and expose the scroll container.
+
+        * UserInterface/Views/Variables.css:
+        (:root):
+        Add a new button hover color, slightly lighter than the existing button active color.
+
+2017-10-04  Joseph Pecoraro  <[email protected]>
+
         Web Inspector: Fix Beacon and Ping folderization issues
         https://bugs.webkit.org/show_bug.cgi?id=177885
 

Modified: trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/Localizations/en.lproj/localizedStrings.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -198,6 +198,7 @@
 localizedStrings["Close %s timeline view"] = "Close %s timeline view";
 localizedStrings["Close Other Tabs"] = "Close Other Tabs";
 localizedStrings["Close Tab"] = "Close Tab";
+localizedStrings["Close detail view"] = "Close detail view";
 localizedStrings["Close resource view"] = "Close resource view";
 localizedStrings["Closed"] = "Closed";
 localizedStrings["Closure Variables"] = "Closure Variables";
@@ -446,6 +447,7 @@
 localizedStrings["Grow"] = "Grow";
 localizedStrings["HTML Attributes"] = "HTML Attributes";
 localizedStrings["HTTP"] = "HTTP";
+localizedStrings["Headers"] = "Headers";
 localizedStrings["Heading Level"] = "Heading Level";
 localizedStrings["Heap Snapshot Object (%s)"] = "Heap Snapshot Object (%s)";
 localizedStrings["Height"] = "Height";
@@ -666,6 +668,7 @@
 localizedStrings["Prefer indent using:"] = "Prefer indent using:";
 localizedStrings["Pressed"] = "Pressed";
 localizedStrings["Pretty print"] = "Pretty print";
+localizedStrings["Preview"] = "Preview";
 localizedStrings["Primary Key"] = "Primary Key";
 localizedStrings["Primary Key \u2014 %s"] = "Primary Key \u2014 %s";
 localizedStrings["Priority"] = "Priority";

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Main.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Main.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -1880,8 +1880,14 @@
 
 WI._focusedContentBrowser = function()
 {
+    if (this.currentFocusElement) {
+        let contentBrowserElement = this.currentFocusElement.enclosingNodeOrSelfWithClass("content-browser");
+        if (contentBrowserElement && contentBrowserElement.__view && contentBrowserElement.__view instanceof WI.ContentBrowser)
+            return contentBrowserElement.__view;
+    }
+
     if (this.tabBrowser.element.isSelfOrAncestor(this.currentFocusElement) || document.activeElement === document.body) {
-        var tabContentView = this.tabBrowser.selectedTabContentView;
+        let tabContentView = this.tabBrowser.selectedTabContentView;
         if (tabContentView.contentBrowser)
             return tabContentView.contentBrowser;
         return null;

Modified: trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/Setting.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -123,6 +123,7 @@
     showScopeChainOnPause: new WI.Setting("show-scope-chain-sidebar", true),
     showImageGrid: new WI.Setting("show-image-grid", false),
     showCanvasPath: new WI.Setting("show-canvas-path", false),
+    selectedNetworkDetailContentViewIdentifier: new WI.Setting("network-detail-content-view-identifier", "preview"),
 
     // Experimental
     experimentalShowCanvasContextsInResources: new WI.Setting("experimental-show-canvas-contexts-in-resources", false),

Modified: trunk/Source/WebInspectorUI/UserInterface/Main.html (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Main.html	2017-10-04 19:17:30 UTC (rev 222868)
@@ -123,6 +123,7 @@
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
+    <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
     <link rel="stylesheet" href=""
@@ -649,6 +650,7 @@
     <script src=""
     <script src=""
     <script src=""
+    <script src=""
     <script src=""
     <script src=""
     <script src=""

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -33,6 +33,6 @@
     flex: 1;
 }
 
-.content-browser > .navigation-bar > .item {
+.content-browser > .navigation-bar .item {
     height: 100%;
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentBrowser.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -25,7 +25,7 @@
 
 WI.ContentBrowser = class ContentBrowser extends WI.View
 {
-    constructor(element, delegate, disableBackForward, disableFindBanner, flexibleNavigationItem)
+    constructor(element, delegate, disableBackForward, disableFindBanner, flexibleNavigationItem, contentViewNavigationItemGroup)
     {
         super(element);
 
@@ -83,6 +83,8 @@
         this._flexibleNavigationItem = flexibleNavigationItem || new WI.FlexibleSpaceNavigationItem;
         this._navigationBar.addNavigationItem(this._flexibleNavigationItem);
 
+        this._currentContentViewNavigationItemsGroup = contentViewNavigationItemGroup || null;
+
         WI.ContentView.addEventListener(WI.ContentView.Event.SelectionPathComponentsDidChange, this._contentViewSelectionPathComponentDidChange, this);
         WI.ContentView.addEventListener(WI.ContentView.Event.SupplementalRepresentedObjectsDidChange, this._contentViewSupplementalRepresentedObjectsDidChange, this);
         WI.ContentView.addEventListener(WI.ContentView.Event.NumberOfSearchResultsDidChange, this._contentViewNumberOfSearchResultsDidChange, this);
@@ -358,6 +360,9 @@
         var selectionPathComponents = contentView ? contentView.selectionPathComponents || [] : [];
         this._contentViewSelectionPathNavigationItem.components = selectionPathComponents;
 
+        if (this._currentContentViewNavigationItemsGroup)
+            return;
+
         if (!selectionPathComponents.length) {
             this._hierarchicalPathNavigationItem.alwaysShowLastPathComponentSeparator = false;
             this._navigationBar.removeNavigationItem(this._contentViewSelectionPathNavigationItem);
@@ -388,6 +393,8 @@
         if (!currentContentView) {
             this._removeAllNavigationItems();
             this._currentContentViewNavigationItems = [];
+            if (this._currentContentViewNavigationItemsGroup)
+                this._currentContentViewNavigationItems.push(this._contentViewSelectionPathNavigationItem);
             return;
         }
 
@@ -412,6 +419,7 @@
 
         // Keep track of items we'll be adding to the navigation bar.
         let newNavigationItems = [];
+        let shouldInsert = !this._currentContentViewNavigationItemsGroup;
 
         // Go through each of the items of the new content view and add a divider before them.
         currentContentView.navigationItems.forEach(function(navigationItem, index) {
@@ -418,13 +426,18 @@
             // Add dividers before items unless it's the first item and not a button.
             if (index !== 0 || navigationItem instanceof WI.ButtonNavigationItem) {
                 let divider = new WI.DividerNavigationItem;
-                navigationBar.insertNavigationItem(divider, insertionIndex++);
+                if (shouldInsert)
+                    navigationBar.insertNavigationItem(divider, insertionIndex++);
                 newNavigationItems.push(divider);
             }
-            navigationBar.insertNavigationItem(navigationItem, insertionIndex++);
+            if (shouldInsert)
+                navigationBar.insertNavigationItem(navigationItem, insertionIndex++);
             newNavigationItems.push(navigationItem);
         });
 
+        if (this._currentContentViewNavigationItemsGroup)
+            this._currentContentViewNavigationItemsGroup.navigationItems = [this._contentViewSelectionPathNavigationItem].concat(newNavigationItems);
+
         // Remember the navigation items we inserted so we can remove them
         // for the next content view.
         this._currentContentViewNavigationItems = newNavigationItems;
@@ -432,9 +445,13 @@
 
     _removeAllNavigationItems()
     {
-        for (let navigationItem of this._currentContentViewNavigationItems) {
-            if (navigationItem.parentNavigationBar)
-                navigationItem.parentNavigationBar.removeNavigationItem(navigationItem);
+        if (this._currentContentViewNavigationItemsGroup)
+            this._currentContentViewNavigationItemsGroup.navigationItems = [];
+        else {
+            for (let navigationItem of this._currentContentViewNavigationItems) {
+                if (navigationItem.parentNavigationBar)
+                    navigationItem.parentNavigationBar.removeNavigationItem(navigationItem);
+            }
         }
     }
 

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/ContentViewContainer.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -83,6 +83,10 @@
         if (!(contentView instanceof WI.ContentView))
             return null;
 
+        // No change.
+        if (contentView === this.currentContentView && !cookie)
+            return contentView;
+
         // ContentViews can be shared between containers. If this content view is
         // not owned by us, it may need to be transferred to this container.
         if (contentView.parentContainer !== this)

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -26,3 +26,11 @@
 :matches(.navigation-bar, .toolbar) .item.flexible-space {
     flex: 1;
 }
+
+:matches(.navigation-bar, .toolbar) .item.flexible-space.align-start > .item {
+    -webkit-margin-end: auto;
+}
+
+:matches(.navigation-bar, .toolbar) .item.flexible-space.align-end > .item {
+    -webkit-margin-start: auto;
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/FlexibleSpaceNavigationItem.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013, 2015 Apple Inc. All rights reserved.
+ * Copyright (C) 2013-2017 Apple Inc. All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -25,6 +25,20 @@
 
 WI.FlexibleSpaceNavigationItem = class FlexibleSpaceNavigationItem extends WI.NavigationItem
 {
+    constructor(navigationItem, alignItem)
+    {
+        super();
+
+        console.assert(!navigationItem || navigationItem instanceof WI.NavigationItem);
+
+        this._navigationItem = navigationItem || null;
+
+        if (this._navigationItem) {
+            this._navigationItem = navigationItem;
+            this.element.classList.add(alignItem || WI.FlexibleSpaceNavigationItem.Align.Start);
+        }
+    }
+
     // Protected
 
     get additionalClassNames()
@@ -31,4 +45,32 @@
     {
         return ["flexible-space"];
     }
+
+    updateLayout(expandOnly)
+    {
+        super.updateLayout(expandOnly);
+
+        if (!this._navigationItem)
+            return;
+
+        if (expandOnly) {
+            let flexibleWidth = this.width;
+            if (!flexibleWidth)
+                return;
+
+            this.element.appendChild(this._navigationItem.element);
+
+            this._navigationItem.updateLayout(true);
+            let itemWidth = this._navigationItem.width;
+
+            let remainingWidth = flexibleWidth - itemWidth;
+            if (remainingWidth <= 0)
+                this.element.removeChild(this._navigationItem.element);
+        }
+    }
 };
+
+WI.FlexibleSpaceNavigationItem.Align = {
+    Start: "align-start",
+    End: "align-end",
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/GroupNavigationItem.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/GroupNavigationItem.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/GroupNavigationItem.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -27,24 +27,41 @@
 {
     constructor(navigationItems)
     {
-        console.assert(Array.isArray(navigationItems));
+        console.assert(!navigationItems || Array.isArray(navigationItems));
 
         super();
 
-        this._navigationItems = navigationItems;
+        this._needsUpdate = false;
 
-        for (let item of this._navigationItems) {
-            console.assert(item instanceof WI.NavigationItem);
-            this.element.appendChild(item.element);
-        }
+        this.navigationItems = navigationItems || [];
     }
 
     // Public
 
-    get navigationItems() { return this._navigationItems; }
+    get navigationItems()
+    {
+        return this._navigationItems;
+    }
+    
+    set navigationItems(items)
+    {
+        this._navigationItems = items;
 
+        // Wait until a layout to update the DOM.
+        this._needsUpdate = true;
+    }
+
+    get width()
+    {
+        this._updateItems();
+
+        return super.width;
+    }
+
     get minimumWidth()
     {
+        this._updateItems();
+
         return this._navigationItems.reduce((total, item) => total + item.minimumWidth, 0);
     }
 
@@ -73,4 +90,21 @@
 
         super.didDetach();
     }
+
+    // Private
+
+    _updateItems()
+    {
+        if (!this._needsUpdate)
+            return;
+
+        this._needsUpdate = false;
+
+        this.element.removeChildren();
+
+        for (let item of this._navigationItems) {
+            console.assert(item instanceof WI.NavigationItem);
+            this.element.appendChild(item.element);
+        }
+    }
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/HierarchicalPathNavigationItem.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -29,6 +29,9 @@
     {
         super(identifier);
 
+        this._collapsedComponent = null;
+        this._needsUpdate = false;
+
         this.components = components;
     }
 
@@ -60,21 +63,19 @@
         if (this._components && componentsEqual(this._components, newComponents))
             return;
 
-        for (var i = 0; this._components && i < this._components.length; ++i)
-            this._components[i].removeEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);
+        if (this._components) {
+            for (let component of this._components)
+                component.removeEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);
+        }
 
-        // Make a shallow copy of the newComponents array using slice.
         this._components = newComponents.slice(0);
 
-        for (var i = 0; i < this._components.length; ++i)
-            this._components[i].addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);
+        for (let component of this._components)
+            component.addEventListener(WI.HierarchicalPathComponent.Event.SiblingWasSelected, this._siblingPathComponentWasSelected, this);
 
-        this.element.removeChildren();
-        delete this._collapsedComponent;
+        // Wait until layout to update the DOM.
+        this._needsUpdate = true;
 
-        for (var i = 0; i < newComponents.length; ++i)
-            this.element.appendChild(newComponents[i].element);
-
         // Update layout for the so other items can adjust to the extra space (or lack thereof) too.
         if (this.parentNavigationBar)
             this.parentNavigationBar.needsLayout();
@@ -100,6 +101,8 @@
 
     updateLayout(expandOnly)
     {
+        this._updateComponentsIfNeeded();
+
         super.updateLayout(expandOnly);
 
         var navigationBar = this.parentNavigationBar;
@@ -108,7 +111,7 @@
 
         if (this._collapsedComponent) {
             this.element.removeChild(this._collapsedComponent.element);
-            delete this._collapsedComponent;
+            this._collapsedComponent = null;
         }
 
         // Expand our components to full width to test if the items can fit at full width.
@@ -244,6 +247,20 @@
 
     // Private
 
+    _updateComponentsIfNeeded()
+    {
+        if (!this._needsUpdate)
+            return;
+
+        this._needsUpdate = false;
+
+        this.element.removeChildren();
+        this._collapsedComponent = null;
+
+        for (let component of this._components)
+            this.element.appendChild(component.element);
+    }
+
     _siblingPathComponentWasSelected(event)
     {
         this.dispatchEventToListeners(WI.HierarchicalPathNavigationItem.Event.PathComponentWasSelected, event.data);

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NavigationBar.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -42,6 +42,9 @@
         this.element.addEventListener("keydown", this._keyDown.bind(this), false);
         this.element.addEventListener("mousedown", this._mouseDown.bind(this), false);
 
+        this._mouseMovedEventListener = this._mouseMoved.bind(this);
+        this._mouseUpEventListener = this._mouseUp.bind(this);
+
         this._forceLayout = false;
         this._minimumWidth = NaN;
         this._navigationItems = [];
@@ -301,9 +304,6 @@
 
         this._mouseIsDown = true;
 
-        this._mouseMovedEventListener = this._mouseMoved.bind(this);
-        this._mouseUpEventListener = this._mouseUp.bind(this);
-
         if (typeof this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown === "function"
             && this.selectedNavigationItem.dontPreventDefaultOnNavigationBarMouseDown()
             && this._previousSelectedNavigationItem === this.selectedNavigationItem)
@@ -363,9 +363,6 @@
         document.removeEventListener("mousemove", this._mouseMovedEventListener, false);
         document.removeEventListener("mouseup", this._mouseUpEventListener, false);
 
-        delete this._mouseMovedEventListener;
-        delete this._mouseUpEventListener;
-
         // Restore the tabIndex so the navigation bar can be in the keyboard tab loop.
         this.element.tabIndex = 0;
 

Copied: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.css (from rev 222867, trunk/Source/WebInspectorUI/UserInterface/Views/Resizer.css) (0 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.css	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+.network-resource-detail {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    /* left or right set by NetworkTableView on display / resize */
+    z-index: 10;
+    background-color: white;
+}
+
+.network-resource-detail .navigation-bar {
+    position: -webkit-sticky;
+    top: 0;
+    z-index: 1;
+}
+
+.network-resource-detail .item.close > .glyph {
+    border-radius: 2px;
+    padding: 2px;
+    background: white;
+}
+
+.network-resource-detail .item.close > .glyph:hover {
+    background-color: var(--button-background-color-hover);
+}
+
+.network-resource-detail .item.close > .glyph:active {
+    background-color: var(--button-background-color-pressed);
+}
+
+.network .network-resource-detail .navigation-bar .item.radio.button.text-only {
+    color: inherit;
+    background-color: inherit;
+}
+
+.network .network-resource-detail .navigation-bar .item.radio.button.text-only.selected {
+    color: var(--selected-background-color);
+    background-color: white;
+}
+
+.network-resource-detail > .content-browser {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+}

Added: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.js (0 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkResourceDetailView.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2017 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.
+ */
+
+WI.NetworkResourceDetailView = class NetworkResourceDetailView extends WI.View
+{
+    constructor(resource, delegate)
+    {
+        super();
+
+        console.assert(resource instanceof WI.Resource);
+
+        this._resource = resource;
+        this._delegate = delegate || null;
+
+        this.element.classList.add("network-resource-detail");
+
+        this._contentBrowser = null;
+        this._headersContentView = null;
+        this._cookiesContentView = null;
+        this._timingContentView = null;
+        this._detailsContentView = null;
+    }
+
+    // Public
+
+    get resource() { return this._resource; }
+
+    shown()
+    {
+        if (!this._contentBrowser)
+            return;
+
+        this._showPreferredContentView();
+        this._contentBrowser.shown();
+    }
+
+    hidden()
+    {
+        this._contentBrowser.hidden();
+    }
+
+    dispose()
+    {
+        this._delegate = null;
+
+        this._contentBrowser.contentViewContainer.closeAllContentViews();
+    }
+
+    // Protected
+
+    initialLayout()
+    {
+        let closeNavigationItem = new WI.ButtonNavigationItem("close", WI.UIString("Close detail view"), "Images/CloseLarge.svg", 16, 16);
+        closeNavigationItem.addEventListener(WI.ButtonNavigationItem.Event.Clicked, this._handleCloseButton.bind(this));
+        closeNavigationItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.High;
+
+        let contentViewNavigationItemsGroup = new WI.GroupNavigationItem;
+        let contentViewNavigationItemsFlexItem = new WI.FlexibleSpaceNavigationItem(contentViewNavigationItemsGroup, WI.FlexibleSpaceNavigationItem.Align.End);
+        contentViewNavigationItemsFlexItem.visibilityPriority = WI.NavigationItem.VisibilityPriority.Low;
+
+        const disableBackForward = true;
+        const disableFindBanner = false;
+        this._contentBrowser = new WI.ContentBrowser(null, this, disableBackForward, disableFindBanner, contentViewNavigationItemsFlexItem, contentViewNavigationItemsGroup);
+
+        // Insert all of our custom navigation items at the start of the ContentBrowser's NavigationBar.
+        let index = 0;
+        this._contentBrowser.navigationBar.insertNavigationItem(closeNavigationItem, index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.FlexibleSpaceNavigationItem, index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.RadioButtonNavigationItem("preview", WI.UIString("Preview")), index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.RadioButtonNavigationItem("headers", WI.UIString("Headers")), index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.RadioButtonNavigationItem("cookies", WI.UIString("Cookies")), index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.RadioButtonNavigationItem("timing", WI.UIString("Timing")), index++);
+        this._contentBrowser.navigationBar.insertNavigationItem(new WI.RadioButtonNavigationItem("details", WI.UIString("Details")), index++);
+        this._contentBrowser.navigationBar.addEventListener(WI.NavigationBar.Event.NavigationItemSelected, this._navigationItemSelected, this);
+
+        this.addSubview(this._contentBrowser);
+
+        this._showPreferredContentView();
+    }
+
+    // Private
+
+    _showPreferredContentView()
+    {
+        // Restore the preferred navigation item.
+        let firstNavigationItem = null;
+        let defaultIdentifier = WI.settings.selectedNetworkDetailContentViewIdentifier.value;
+        for (let navigationItem of this._contentBrowser.navigationBar.navigationItems) {
+            if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
+                continue;
+
+            if (!firstNavigationItem)
+                firstNavigationItem = navigationItem;
+
+            if (navigationItem.identifier === defaultIdentifier) {
+                this._contentBrowser.navigationBar.selectedNavigationItem = navigationItem;
+                return;
+            }
+        }
+
+        console.assert(firstNavigationItem, "Should have found at least one navigation item above");
+        this._contentBrowser.navigationBar.selectedNavigationItem = firstNavigationItem;
+    }
+
+    _showContentViewForNavigationItem(navigationItem)
+    {
+        switch (navigationItem.identifier) {
+        case "preview":
+            this._contentBrowser.showContentViewForRepresentedObject(this._resource);
+            break;
+        case "headers":
+            // FIXME: Provide a Resource Headers View.
+            if (!this._headersContentView)
+                this._headersContentView = new WI.DebugContentView("Headers");
+            this._contentBrowser.showContentView(this._headersContentView);
+            break;
+        case "cookies":
+            // FIXME: Provide a Resource Cookies View.
+            if (!this._cookiesContentView)
+                this._cookiesContentView = new WI.DebugContentView("Cookies");
+            this._contentBrowser.showContentView(this._cookiesContentView);
+            break;
+        case "timing":
+            // FIXME: Provide a Resource Timing View.
+            if (!this._timingContentView)
+                this._timingContentView = new WI.DebugContentView("Timing");
+            this._contentBrowser.showContentView(this._timingContentView);
+            break;
+        case "details":
+            // FIXME: Provide a Resource Details View.
+            if (!this._detailsContentView)
+                this._detailsContentView = new WI.DebugContentView("Details");
+            this._contentBrowser.showContentView(this._detailsContentView);
+            break;
+        }
+    }
+
+    _navigationItemSelected(event)
+    {
+        let navigationItem = event.target.selectedNavigationItem;
+        if (!(navigationItem instanceof WI.RadioButtonNavigationItem))
+            return;
+
+        this._showContentViewForNavigationItem(navigationItem);
+
+        console.assert(navigationItem.identifier);
+        WI.settings.selectedNetworkDetailContentViewIdentifier.value = navigationItem.identifier;
+    }
+
+    _handleCloseButton(event)
+    {
+        if (this._delegate && this._delegate.networkResourceDetailViewClose)
+            this._delegate.networkResourceDetailViewClose(this);
+    }
+};

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -59,3 +59,11 @@
     width: 14px;
     height: 14px;
 }
+
+.showing-detail .table .cell:not(.name) {
+    display: none;
+}
+
+.showing-detail .table .resizer:not(:first-of-type) {
+    display: none;
+}

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTableContentView.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -38,7 +38,10 @@
         this._table = null;
         this._nameColumnWidthSetting = new WI.Setting("network-table-content-view-name-column-width", 250);
 
-        // FIXME: Resource Detail View.
+        this._selectedResource = null;
+        this._resourceDetailView = null;
+        this._resourceDetailViewMap = new Map;
+
         // FIXME: Network Timeline.
         // FIXME: Filter text field.
         // FIXME: Throttling.
@@ -143,17 +146,34 @@
     {
         super.shown();
 
+        if (this._resourceDetailView)
+            this._resourceDetailView.shown();
+
         if (this._table)
             this._table.restoreScrollPosition();
     }
 
+    hidden()
+    {
+        if (this._resourceDetailView)
+            this._resourceDetailView.hidden();
+
+        super.hidden();
+    }
+
     closed()
     {
-        super.closed();
+        this._hideResourceDetailView();
 
+        for (let detailView of this._resourceDetailViewMap.values())
+            detailView.dispose();
+        this._resourceDetailViewMap.clear();
+
         WI.Frame.removeEventListener(null, null, this);
         WI.Resource.removeEventListener(null, null, this);
         WI.timelineManager.persistentNetworkTimeline.removeEventListener(WI.Timeline.Event.RecordAdded, this._networkTimelineRecordAdded, this);
+
+        super.closed();
     }
 
     reset()
@@ -162,12 +182,27 @@
         this._filteredEntries = [];
         this._pendingInsertions = [];
 
+        for (let detailView of this._resourceDetailViewMap.values())
+            detailView.dispose();
+        this._resourceDetailViewMap.clear();
+
         if (this._table) {
+            this._hideResourceDetailView();
+            this._selectedResource = null;
             this._table.clearSelectedRow();
             this._table.reloadData();
         }
     }
 
+    // NetworkResourceDetailView delegate
+
+    networkResourceDetailViewClose(resourceDetailView)
+    {
+        this._hideResourceDetailView();
+        this._selectedResource = null;
+        this._table.clearSelectedRow();
+    }
+
     // Table dataSource
 
     tableNumberOfRows(table)
@@ -182,6 +217,8 @@
         if (!this._entriesSortComparator)
             return;
 
+        this._hideResourceDetailView();
+
         this._entries = this._entries.sort(this._entriesSortComparator);
         this._updateFilteredEntries();
         this._table.reloadData();
@@ -191,7 +228,10 @@
 
     tableCellClicked(table, cell, column, rowIndex, event)
     {
-        // FIXME: Show resource detail view.
+        if (column !== this._nameColumn)
+            return;
+
+        this._table.selectRow(rowIndex);
     }
 
     tableCellContextMenuClicked(table, cell, column, rowIndex, event)
@@ -208,7 +248,18 @@
 
     tableSelectedRowChanged(table, rowIndex)
     {
-        // FIXME: Show resource detail view.
+        if (isNaN(rowIndex)) {
+            this._selectedResource = null;
+            this._hideResourceDetailView();
+            return;
+        }
+
+        let entry = this._filteredEntries[rowIndex];
+        if (entry.resource === this._selectedResource)
+            return;
+
+        this._selectedResource = entry.resource;
+        this._showResourceDetailView(this._selectedResource);
     }
 
     tablePopulateCell(table, cell, column, rowIndex)
@@ -521,6 +572,7 @@
     layout()
     {
         this._processPendingEntries();
+        this._positionDetailView();
     }
 
     handleClearShortcut(event)
@@ -577,6 +629,58 @@
         this._filteredEntries[rowIndex] = entry;
     }
 
+    _hideResourceDetailView()
+    {
+        if (!this._resourceDetailView)
+            return;
+
+        this.element.classList.remove("showing-detail");
+        this._table.scrollContainer.style.removeProperty("width");
+
+        this.removeSubview(this._resourceDetailView);
+
+        this._resourceDetailView.hidden();
+        this._resourceDetailView = null;
+
+        this._table.resize();
+    }
+
+    _showResourceDetailView(resource)
+    {
+        let oldResourceDetailView = this._resourceDetailView;
+
+        this._resourceDetailView = this._resourceDetailViewMap.get(resource);
+        if (!this._resourceDetailView) {
+            this._resourceDetailView = new WI.NetworkResourceDetailView(resource, this);
+            this._resourceDetailViewMap.set(resource, this._resourceDetailView);
+        }
+
+        if (oldResourceDetailView) {
+            oldResourceDetailView.hidden();
+            this.replaceSubview(oldResourceDetailView, this._resourceDetailView);
+        } else
+            this.addSubview(this._resourceDetailView);
+        this._resourceDetailView.shown();
+
+        this.element.classList.add("showing-detail");
+        this._table.scrollContainer.style.width = this._nameColumn.width + "px";
+
+        // FIXME: It would be nice to avoid this.
+        // Currently the ResourceDetailView is in the heirarchy but has not yet done a layout so we
+        // end up seeing the table behind it. This forces us to layout now instead of after a beat.
+        this.updateLayout();
+    }
+
+    _positionDetailView()
+    {
+        if (!this._resourceDetailView)
+            return;
+
+        let side = WI.resolvedLayoutDirection() === WI.LayoutDirection.RTL ? "right" : "left";
+        this._resourceDetailView.element.style[side] = this._nameColumn.width + "px";
+        this._table.scrollContainer.style.width = this._nameColumn.width + "px";
+    }
+
     _resourceCachingDisabledSettingChanged()
     {
         this._disableResourceCacheNavigationItem.activated = WI.resourceCachingDisabledSetting.value;
@@ -753,6 +857,8 @@
             this._filteredEntries = this._entries.filter(this._passFilter, this);
         else
             this._filteredEntries = this._entries.slice();
+
+        this._restoreSelectedRow();
     }
 
     _generateTypeFilter()
@@ -790,13 +896,33 @@
         if (this._areFilterListsIdentical(oldFilter, newFilter))
             return;
 
+        // Even if the selected resource would still be visible, lets close the detail view if a filter changes.
+        this._hideResourceDetailView();
+
         this._activeTypeFilters = newFilter;
         this._updateFilteredEntries();
         this._table.reloadData();
     }
 
+    _restoreSelectedRow()
+    {
+        if (!this._selectedResource)
+            return;
+
+        let rowIndex = this._rowIndexForResource(this._selectedResource);
+        if (rowIndex === -1) {
+            this._selectedResource = null;
+            this._table.clearSelectedRow();
+            return;
+        }
+
+        this._table.selectRow(rowIndex);
+    }
+
     _tableNameColumnDidChangeWidth(event)
     {
         this._nameColumnWidthSetting.value = event.target.width;
+
+        this._positionDetailView();
     }
 };

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Resizer.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Resizer.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Resizer.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -26,6 +26,7 @@
 .resizer {
     position: absolute;
     z-index: var(--z-index-resizer);
+    pointer-events: all;
 }
 
 .resizer.vertical-rule {

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Table.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Table.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Table.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -94,6 +94,15 @@
     overflow-y: scroll;
 }
 
+.table > .resizers {
+    position: absolute;
+    top: 0;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    pointer-events: none;
+}
+
 .table > .data-container.not-scrollable {
     overflow-y: hidden;
 }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Table.js (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Table.js	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Table.js	2017-10-04 19:17:30 UTC (rev 222868)
@@ -73,6 +73,9 @@
         this._fillerRow = this._listElement.appendChild(document.createElement("li"));
         this._fillerRow.className = "filler";
 
+        this._resizersElement = this._element.appendChild(document.createElement("div"));
+        this._resizersElement.className = "resizers";
+
         this._cachedRows = new Map;
 
         this._columnSpecs = new Map;
@@ -121,6 +124,7 @@
     get delegate() { return this._delegate; }
     get rowHeight() { return this._rowHeight; }
     get selectedRow() { return this._selectedRowIndex; }
+    get scrollContainer() { return this._scrollContainerElement; }
 
     get sortOrder()
     {
@@ -986,12 +990,12 @@
                 do {
                     let resizer = new WI.Resizer(WI.Resizer.RuleOrientation.Vertical, this);
                     this._resizers.push(resizer);
-                    this.element.appendChild(resizer.element);
+                    this._resizersElement.appendChild(resizer.element);
                 } while (this._resizers.length < resizersNeededCount);
             } else {
                 do {
                     let resizer = this._resizers.pop();
-                    this.element.removeChild(resizer.element);
+                    this._resizersElement.removeChild(resizer.element);
                 } while (this._resizers.length > resizersNeededCount);
             }
         }

Modified: trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css (222867 => 222868)


--- trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css	2017-10-04 18:59:04 UTC (rev 222867)
+++ trunk/Source/WebInspectorUI/UserInterface/Views/Variables.css	2017-10-04 19:17:30 UTC (rev 222868)
@@ -50,6 +50,7 @@
     --border-color-dark: hsl(0, 0%, 57%);
 
     --button-background-color: white;
+    --button-background-color-hover: hsl(0, 0%, 88%);
     --button-background-color-pressed: hsl(0, 0%, 85%);
 
     --panel-background-color: hsl(0, 0%, 93%);
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to